Skip to content

Commit

Permalink
feature: cloudcmd: readonly (#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
coderaiser committed Mar 11, 2024
1 parent 1d3567f commit c710b29
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 3 deletions.
2 changes: 2 additions & 0 deletions HELP.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Cloud Commander supports the following command-line parameters:
| `--config-auth` | enable auth change in config dialog
| `--console` | enable console
| `--sync-console-path` | sync console path
| `--readonly` | disable ui related to filesystem modifications
| `--terminal` | enable terminal
| `--terminal-path` | set terminal path
| `--terminal-command` | set command to run in terminal (shell by default)
Expand Down Expand Up @@ -403,6 +404,7 @@ Here's a description of all options:
"configAuth": true, // enable auth change in config dialog
"console": true, // enable console
"syncConsolePath": false, // do not sync console path
"readonly": false, // disable ui related to filesystem modifications
"terminal": false, // disable terminal
"terminalPath": "", // path of a terminal
"terminalCommand": "", // set command to run in terminal
Expand Down
4 changes: 4 additions & 0 deletions bin/cloudcmd.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const yargsOptions = {
'config-auth',
'console',
'sync-console-path',
'readonly',
'contact',
'terminal',
'terminal-auto-restart',
Expand All @@ -105,6 +106,7 @@ const yargsOptions = {
'port': config('port'),
'online': config('online'),
'open': choose(env.bool('open'), config('open')),
'readonly': env.bool('readonly') || config('readonly'),
'editor': env('editor') || config('editor'),
'packer': config('packer') || 'tar',
'zip': config('zip'),
Expand Down Expand Up @@ -205,6 +207,8 @@ async function main() {
config('configDialog', args.configDialog);
config('configAuth', args.configAuth);
config('keysPanel', args.keysPanel);
config('readonly', args.readonly);

config('export', args.export);
config('exportToken', args.exportToken);
config('import', args.import);
Expand Down
26 changes: 24 additions & 2 deletions client/modules/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,39 @@ function getFileMenuData() {
},
};

const menuDataFile = {
const menuDataFile = maybeReadonly({
...menuTop,
...menuBottom,
};
});

return {
isAuth,
menuDataFile,
};
}

function maybeReadonly(menu) {
const operations = [
'Edit',
'Rename',
'Delete',
'Pack',
'Extract',
'Cut',
'Copy',
'Paste',
'New',
'Upload',
'Upload From Cloud',
];

for (const operation of operations) {
delete menu[operation];
}

return menu;
}

function isCurrent(yesFn, noFn) {
if (Info.name !== '..')
return yesFn();
Expand Down
3 changes: 3 additions & 0 deletions client/modules/operation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const noFilesCheck = () => {
};

module.exports.init = promisify((callback) => {
if (config('readonly'))
return;

showLoad();

exec.series([
Expand Down
1 change: 1 addition & 0 deletions json/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"root": "/",
"prefix": "",
"prefixSocket": "",
"readonly": false,
"contact": true,
"confirmCopy": true,
"confirmMove": true,
Expand Down
11 changes: 11 additions & 0 deletions server/cloudcmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const html = fs.readFileSync(getIndexPath(isDev), 'utf8');
const initAuth = currify(_initAuth);
const notEmpty = (a) => a;
const clean = (a) => a.filter(notEmpty);
const createReadonly = (config) => () => config('readonly');

const isUndefined = (a) => typeof a === 'undefined';
const isFn = (a) => typeof a === 'function';
Expand Down Expand Up @@ -131,25 +132,29 @@ function _initAuth(config, accept, reject, username, password) {
function listen({prefixSocket, socket, config}) {
const root = apart(config, 'root');
const auth = initAuth(config);
const readonly = createReadonly(config);

prefixSocket = getPrefix(prefixSocket);
config.listen(socket, auth);

edward.listen(socket, {
root,
auth,
readonly,
prefixSocket: `${prefixSocket}/edward`,
});

dword.listen(socket, {
root,
auth,
readonly,
prefixSocket: `${prefixSocket}/dword`,
});

deepword.listen(socket, {
root,
auth,
readonly,
prefixSocket: `${prefixSocket}/deepword`,
});

Expand All @@ -161,6 +166,7 @@ function listen({prefixSocket, socket, config}) {
fileop.listen(socket, {
root,
auth,
readonly,
prefix: `${prefixSocket}/fileop`,
});

Expand All @@ -180,6 +186,7 @@ function cloudcmd({modules, config}) {
const diff = apart(config, 'diff');
const zip = apart(config, 'zip');
const root = apart(config, 'root');
const readonly = createReadonly(config);

const ponseStatic = ponse.static({
cache,
Expand All @@ -201,6 +208,7 @@ function cloudcmd({modules, config}) {
zip,
dropbox,
dropboxToken,
readonly,
}),
dword({
root,
Expand All @@ -209,6 +217,7 @@ function cloudcmd({modules, config}) {
zip,
dropbox,
dropboxToken,
readonly,
}),
deepword({
root,
Expand All @@ -217,6 +226,7 @@ function cloudcmd({modules, config}) {
zip,
dropbox,
dropboxToken,
readonly,
}),
fileop(),
nomine(),
Expand All @@ -233,6 +243,7 @@ function cloudcmd({modules, config}) {
}),
restafary({
prefix: cloudfunc.apiURL + '/fs',
readonly,
root,
}),
userMenu({
Expand Down
3 changes: 3 additions & 0 deletions server/rest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ module.exports._onPUT = onPUT;
function onPUT({name, config, body}, callback) {
checkPut(name, body, callback);

if (config('readonly'))
callback(UserError('"readonly" mode enabled'));

const cmd = getCMD(name);
const files = json.parse(body);
const rootDir = config('root');
Expand Down
11 changes: 10 additions & 1 deletion server/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ async function route({config, options, request, response}) {
* additional processing of index file
*/
function indexProcessing(config, options) {
const readonly = config('readonly');
const oneFilePanel = config('oneFilePanel');
const noKeysPanel = !config('keysPanel');
const noContact = !config('contact');
Expand All @@ -124,10 +125,18 @@ function indexProcessing(config, options) {
if (noKeysPanel)
data = hideKeysPanel(data);

if (oneFilePanel)
if (readonly) {
data = data
.replace('icon-move', 'icon-move none')
.replace('icon-copy', 'icon-copy none')
.replace('icon-edit', 'icon-edit none')
.replace('icon-directory', 'icon-directory none')
.replace('icon-delete', 'icon-delete none');
} else if (oneFilePanel) {
data = data
.replace('icon-move', 'icon-move none')
.replace('icon-copy', 'icon-copy none');
}

if (noContact)
data = data.replace('icon-contact', 'icon-contact none');
Expand Down
17 changes: 17 additions & 0 deletions server/route.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,23 @@ test('cloudcmd: route: keys panel', async (t) => {
t.end();
});

test('cloudcmd: route: readonly', async (t) => {
const config = {
readonly: true,
};

const options = {
config,
};

const {body} = await request.get('/', {
options,
});

t.match(body, 'icon-edit none', 'should hide edit');
t.end();
});

test('cloudcmd: route: symlink', async (t) => {
const emptyDir = path.join(fixtureDir, 'empty-dir');
const root = fixtureDir;
Expand Down
27 changes: 27 additions & 0 deletions test/rest/move.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,30 @@ test('cloudcmd: rest: move: no to', async (t) => {
t.equal(body, expected);
t.end();
});

test('cloudcmd: rest: readonly', async (t) => {
const cloudcmd = reRequire(cloudcmdPath);
const {createConfigManager} = cloudcmd;

const configManager = createConfigManager();
configManager('auth', false);
configManager('root', '/');
configManager('readonly', true);

const {request} = serveOnce(cloudcmd, {
configManager,
});

const files = {
from: '/',
};

const {body} = await request.put(`/api/v1/move`, {
body: files,
});

const expected = '"readonly" mode enabled';

t.equal(body, expected);
t.end();
});
6 changes: 6 additions & 0 deletions tmpl/config.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@
Confirm Move
</label>
</li>
<li title="Readonly">
<label>
<input data-name="js-readonly" type="checkbox" {{ readonly }}>
Readonly
</label>
</li>
<li title="Synchronize path of current directory with Console">
<label>
<input data-name="js-syncConsolePath" type="checkbox" {{ syncConsolePath }}>
Expand Down

0 comments on commit c710b29

Please sign in to comment.