diff --git a/client/pages/adminpage.js b/client/pages/adminpage.js index 24fc217b..653e253b 100644 --- a/client/pages/adminpage.js +++ b/client/pages/adminpage.js @@ -13,7 +13,7 @@ import { t } from "../locales/"; function AdminOnly(WrappedComponent) { let initIsAdmin = null; - return function(props) { + return function AdminOnlyComponent(props) { const [isAdmin, setIsAdmin] = useState(initIsAdmin); const refresh = () => { diff --git a/client/pages/adminpage/backend.js b/client/pages/adminpage/backend.js index 55f374c1..534f3346 100644 --- a/client/pages/adminpage/backend.js +++ b/client/pages/adminpage/backend.js @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ import React from "react"; import { FormBuilder, Icon, Input, Alert } from "../../components/"; import { Backend, Config } from "../../model/"; @@ -7,41 +8,42 @@ import { t } from "../../locales/"; import "./backend.scss"; export class BackendPage extends React.Component { - constructor(props){ + constructor(props) { super(props); this.state = { backend_enabled: [], backend_available: [], auth_available: ["LDAP", "SAML", "OpenID", "External"], auth_enabled: null, - config: null + config: null, }; } - componentDidMount(){ + componentDidMount() { Promise.all([ Backend.all(), - Config.all() + Config.all(), ]).then((data) => { - let [backend, config] = data; + const [backend, config] = data; this.setState({ backend_available: backend, backend_enabled: window.CONFIG["connections"].filter((b) => b).map((conn) => { return createFormBackend(backend, conn); }), - config: config + config: config, }); }); } - onChange(e){ - this.setState({refresh: Math.random()}); // refresh the screen to refresh the mutation - // that have happenned down the stack + onChange(e) { + // refresh the screen to refresh the mutation + // that have happenned down the stack + this.setState({ refresh: Math.random() }); - let json = FormObjToJSON(this.state.config); + const json = FormObjToJSON(this.state.config); json.connections = this.state.backend_enabled.map((backend) => { - let data = FormObjToJSON(backend, (obj, key) => { - if(obj[key].enabled === true){ + const data = FormObjToJSON(backend, (obj, key) => { + if (obj[key].enabled === true) { obj[key] = obj[key].value || obj[key].default; } else { delete obj[key]; @@ -61,41 +63,41 @@ export class BackendPage extends React.Component { }); } - addBackend(backend_id){ + addBackend(backend_id) { this.setState({ backend_enabled: this.state.backend_enabled.concat( createFormBackend(this.state.backend_available, { type: backend_id, - label: backend_id.toUpperCase() - }) - ) + label: backend_id.toUpperCase(), + }), + ), }, this.onChange.bind(this)); } - removeBackend(n){ + removeBackend(n) { this.setState({ - backend_enabled: this.state.backend_enabled.filter((_, i) => i !== n) + backend_enabled: this.state.backend_enabled.filter((_, i) => i !== n), }, this.onChange.bind(this)); } - onClickAuthAvailable(auth){ + onClickAuthAvailable(auth) { this.setState({ - auth_enabled: this.state.auth_enabled === auth ? null : auth + auth_enabled: this.state.auth_enabled === auth ? null : auth, }); } - render(){ + render() { const update = (value, struct) => { struct.enabled = value; - this.setState({refresh: Math.random()}); - if(value === false){ + this.setState({ refresh: Math.random() }); + if (value === false) { struct.value = null; } return; }; const enable = (struct) => { - if(typeof struct.value === "string"){ + if (typeof struct.value === "string") { struct.enabled = true; return true; } @@ -112,117 +114,131 @@ export class BackendPage extends React.Component { return auth_key === this.state.auth_enabled; }; + const renderForm = ($input, props, struct, onChange) => { + let $checkbox = ( + onChange(update.bind(this, e.target.checked))} /> + ); + if (struct.label === "label") { + $checkbox = null; + } else if (struct.readonly === true) { + $checkbox = null; + } + return ( + + ); + }; + return (
-

Enabled Backends

-
- { - Object.keys(this.state.backend_available) - .sort((a, b) => a > b) - .map((backend_available, index) => ( -
-
- { backend_available } - - + - -
+

Enabled Backends

+
+ { + Object.keys(this.state.backend_available) + .sort((a, b) => a > b) + .map((backend_available, index) => ( +
+
+ { backend_available } + + + + +
+
+ )) + } +
+ +

Authentication Middleware

+ + + Integrate Filestash with your identity management system + + +
+ { + this.state.auth_available.map((auth) => ( +
+
+ { auth } + + + { isActiveAuth(auth) === false ? "+" : + } + + +
)) - } -
+ } +
-

Authentication Middleware

- - - Integrate Filestash with your identity management system - - -
{ - this.state.auth_available.map((auth) => ( -
-
- { auth } - - - { isActiveAuth(auth) === false ? "+" : } - - -
-
- )) + this.state.auth_enabled !== null && ( + + + + Register your interest: + + mickael@kerjean.me + + + + + + ) } -
- { - this.state.auth_enabled !== null && ( - - - Register your interest: mickael@kerjean.me - - - ) - } +

Backend Configuration

-

Backend Configuration

- - { - this.state.backend_enabled.length !== 0 ?
-
- { - this.state.backend_enabled.map((backend_enable, index) => { - return ( -
-
- -
- { - let $checkbox = ( - onChange(update.bind(this, e.target.checked))}/> - ); - if(struct.label === "label"){ - $checkbox = null; - } else if(struct.readonly === true) { - $checkbox = null; - } - return ( - - ); - }} /> -
- ); - }) - } -
-
: You need to enable a backend first. - } + { + this.state.backend_enabled.length !== 0 ? ( +
+
+ { + this.state.backend_enabled.map((backend_enable, index) => { + return ( +
+
+ +
+ +
+ ); + }) + } +
+
+ ) : You need to enable a backend first. + }
); } diff --git a/client/pages/adminpage/loginpage.js b/client/pages/adminpage/loginpage.js index 074e102c..12dfb306 100644 --- a/client/pages/adminpage/loginpage.js +++ b/client/pages/adminpage/loginpage.js @@ -1,5 +1,4 @@ -import React, { useState, useRef } from "react"; -import { Redirect } from "react-router"; +import React, { useState, useEffect, useRef } from "react"; import { Input, Button, Container, Icon } from "../../components/"; import { Admin } from "../../model/"; @@ -9,36 +8,36 @@ import { t } from "../../locales/"; export function LoginPage({ reload = nop }) { const [isLoading, setIsLoading] = useState(false); const [hasError, setHasError] = useState(false); - const $input = useRef(); - const marginTop = () => ({ marginTop: `${parseInt(window.innerHeight / 3)}px` }) + const $input = useRef(null); + const marginTop = () => ({ marginTop: `${parseInt(window.innerHeight / 3)}px` }); const authenticate = (e) => { e.preventDefault(); setIsLoading(true); Admin.login($input.current.ref.value) .then(() => reload()) - .catch(() => { + .catch(() => { $input.current.ref.value = ""; - setIsLoading(false) + setIsLoading(false); setHasError(true); setTimeout(() => { setHasError(false); }, 500); }); - } + }; - useRef(() => { + useEffect(() => { $input.current.ref.focus(); }, []); - return ( -
+
- ) + ); } diff --git a/client/pages/adminpage/settings.js b/client/pages/adminpage/settings.js index ebfd7540..958c1ef6 100644 --- a/client/pages/adminpage/settings.js +++ b/client/pages/adminpage/settings.js @@ -1,71 +1,76 @@ import React, { useState, useEffect } from "react"; import { FormBuilder } from "../../components/"; import { Config } from "../../model/"; -import { format, notify, nop } from "../../helpers"; +import { notify, nop } from "../../helpers"; import { t } from "../../locales/"; export function SettingsPage({ isSaving = nop }) { const [form, setForm] = useState({}); const format = (name) => { - if(typeof name !== "string"){ + if (typeof name !== "string") { return "N/A"; } return name .split("_") .map((word) => { - if(word.length < 1){ + if (word.length < 1) { return word; } return word[0].toUpperCase() + word.substring(1); }) .join(" "); - } + }; const onChange = (_form) => { _form.connections = window.CONFIG.connections; delete _form.constant; - refresh(Math.random()) - isSaving(true) + refresh(Math.random()); + isSaving(true); Config.save(_form, true, () => { - isSaving(false) + isSaving(false); }, (err) => { - isSaving(false) + isSaving(false); notify.send(err && err.message || t("Oops"), "error"); }); - } - const [_, refresh] = useState(null); + }; + const refresh = useState(null)[1]; useEffect(() => { Config.all().then((c) => { - delete c.constant; // The constant key contains read only global variable that are - // application wide truth => not editable from the admin area - setForm(c) + // The constant key contains read only global variable that are + // application wide truth => not editable from the admin area + delete c.constant; + setForm(c); }); }, []); + const renderForm = ($input, props, struct, onChange) => ( + + ); + return (
( - - )} /> - + render={renderForm} /> + ); } diff --git a/client/pages/adminpage/setup.js b/client/pages/adminpage/setup.js index 00217c06..a9612e7a 100644 --- a/client/pages/adminpage/setup.js +++ b/client/pages/adminpage/setup.js @@ -1,15 +1,16 @@ +/* eslint-disable max-len */ import React, { createRef } from "react"; +import ReactCSSTransitionGroup from "react-addons-css-transition-group"; -import { Input, Button, Container, Icon, NgIf, Loader, CSSTransition } from "../../components/"; +import { Input, Button, Icon, NgIf, Loader } from "../../components/"; import { Config, Admin } from "../../model/"; -import { notify, FormObjToJSON, alert, prompt } from "../../helpers"; +import { notify, FormObjToJSON, alert } from "../../helpers"; import { bcrypt_password } from "../../helpers/bcrypt"; -//import ReactCSSTransitionGroup from "react-addons-css-transition-group"; import "./setup.scss"; export class SetupPage extends React.Component { - constructor(props){ + constructor(props) { super(props); this.state = { busy: false, @@ -23,28 +24,33 @@ export class SetupPage extends React.Component { }; Config.all().then((config) => { - if(config.log.telemetry.value === true) return; + if (config.log.telemetry.value === true) return; this.unlisten = this.props.history.listen((location, action) => { this.unlisten(); alert.now((
-

- Help making this software better by sending crash reports and anonymous usage statistics -

-
- -
+

+ Help making this software better by sending crash reports and + anonymous usage statistics +

+
+ +
)); }); }); } - onAdminPassword(p, done){ - this.setState({busy: true}); + onAdminPassword(p, done) { + this.setState({ busy: true }); Config.all().then((config) => { return bcrypt_password(p).then((hash) => { config = FormObjToJSON(config); @@ -52,22 +58,22 @@ export class SetupPage extends React.Component { config.auth.admin = hash; Config.save(config, false) .then(() => Admin.login(p)) - .then(() => this.setState({busy: false}, done)) + .then(() => this.setState({ busy: false }, done)) .catch((err) => { - this.setState({busy: false}); + this.setState({ busy: false }); notify.send(err && err.message, "error"); }); }).catch((err) => { - this.setState({busy: false}); + this.setState({ busy: false }); notify.send("Hash error: " + JSON.stringify(err), "error"); }); }).catch((err) => { notify.send(err && err.message, "error"); - this.setState({busy: false}); + this.setState({ busy: false }); }); } - enableLog(value){ + enableLog(value) { Config.all().then((config) => { config = FormObjToJSON(config); config.connections = window.CONFIG.connections; @@ -76,49 +82,49 @@ export class SetupPage extends React.Component { }); }; - summaryCall(){ - this.setState({busy: true}); + summaryCall() { + this.setState({ busy: true }); return Config.all().then((config) => { - this.setState({busy: false}); + this.setState({ busy: false }); return [ { "name_success": "SSL is configured properly", "name_failure": "SSL is not configured properly", "pass": window.location.protocol !== "http:", "severe": true, - "message": "This can lead to data leaks. Please use a SSL certificate" + "message": "This can lead to data leaks. Please use a SSL certificate", }, { "name_success": "Application is running as '" + objectGet(config, ["constant", "user", "value"]) + "'", "name_failure": "Application is running as root", "pass": objectGet(config, ["constant", "user", "value"]) !== "root", "severe": true, - "message": "This is dangerous, you should use another user with less privileges" + "message": "This is dangerous, you should use another user with less privileges", }, { "name_success": "Emacs is installed", "name_failure": "Emacs is not installed", "pass": objectGet(config, ["constant", "emacs", "value"]), "severe": false, - "message": "If you want to use all the org-mode features of Filestash, you need to install emacs" + "message": "If you want to use all the org-mode features of Filestash, you need to install emacs", }, { "name_success": "Pdftotext is installed", "name_failure": "Pdftotext is not installed", "pass": objectGet(config, ["constant", "pdftotext", "value"]), "severe": false, - "message": "You won't be able to search through PDF documents without it" - } + "message": "You won't be able to search through PDF documents without it", + }, ]; }).catch((err) => { notify.send(err && err.message, "error"); - this.setState({busy: false}); + this.setState({ busy: false }); }); } - render(){ + render() { return (
- +
); } @@ -126,86 +132,101 @@ export class SetupPage extends React.Component { class MultiStepForm extends React.Component { - constructor(props){ + constructor(props) { super(props); this.state = { current: parseInt(window.location.hash.replace("#", "")) || 0, answer_password: "", has_answered_password: false, - deps: [] + deps: [], }; - this.$input = createRef() + this.$input = createRef(); } - componentDidMount(){ - if(this.state.current === 1){ + componentDidMount() { + if (this.state.current === 1) { this.props.summaryCall().then((deps) => { - this.setState({deps: deps}); + this.setState({ deps: deps }); }); } } - onAdminPassword(e){ + onAdminPassword(e) { e.preventDefault(); this.props.onAdminPassword(this.state.answer_password, () => { - this.setState({has_answered_password: true}); + this.setState({ has_answered_password: true }); this.onStepChange(1); }); } - onStepChange(n){ - this.setState({current: n}, () => { - if(n === 1) this.componentDidMount(); + onStepChange(n) { + this.setState({ current: n }, () => { + if (n === 1) this.componentDidMount(); }); } render() { - const hideMenu =