mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) apply access control to code view
Summary: Names of private tables and columns were leaking via Code View. This plugs that leak. Test Plan: adds test Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2840
This commit is contained in:
parent
96fee73b70
commit
37698f9cb5
@ -17,3 +17,7 @@
|
|||||||
.g-code-viewer.hljs {
|
.g-code-viewer.hljs {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.g-code-panel-denied {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ hljs.registerLanguage('python', require('highlight.js/lib/languages/python'));
|
|||||||
function CodeEditorPanel(gristDoc) {
|
function CodeEditorPanel(gristDoc) {
|
||||||
this._gristDoc = gristDoc;
|
this._gristDoc = gristDoc;
|
||||||
this._schema = ko.observable('');
|
this._schema = ko.observable('');
|
||||||
|
this._denied = ko.observable(false);
|
||||||
|
|
||||||
this.listenTo(this._gristDoc, 'schemaUpdateAction', this.onSchemaAction);
|
this.listenTo(this._gristDoc, 'schemaUpdateAction', this.onSchemaAction);
|
||||||
this.onSchemaAction(); // Fetch the schema to initialize
|
this.onSchemaAction(); // Fetch the schema to initialize
|
||||||
@ -28,6 +29,10 @@ CodeEditorPanel.prototype.buildDom = function() {
|
|||||||
// interfere with text selection even for un-focusable elements.
|
// interfere with text selection even for un-focusable elements.
|
||||||
return dom('div.g-code-panel.clipboard',
|
return dom('div.g-code-panel.clipboard',
|
||||||
{tabIndex: "-1"},
|
{tabIndex: "-1"},
|
||||||
|
kd.maybe(this._denied, () => dom('div.g-code-panel-denied',
|
||||||
|
dom('h2', kd.text('Access denied')),
|
||||||
|
dom('div', kd.text('Code View is available only when you have full document access.')),
|
||||||
|
)),
|
||||||
kd.scope(this._schema, function(schema) {
|
kd.scope(this._schema, function(schema) {
|
||||||
// The reason to scope and rebuild instead of using `kd.text(schema)` is because
|
// The reason to scope and rebuild instead of using `kd.text(schema)` is because
|
||||||
// hljs.highlightBlock(elem) replaces `elem` with a whole new dom tree.
|
// hljs.highlightBlock(elem) replaces `elem` with a whole new dom tree.
|
||||||
@ -45,13 +50,22 @@ CodeEditorPanel.prototype.buildDom = function() {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
CodeEditorPanel.prototype.onSchemaAction = function(actions) {
|
CodeEditorPanel.prototype.onSchemaAction = async function(actions) {
|
||||||
return this._gristDoc.docComm.fetchTableSchema()
|
try {
|
||||||
.then(schema => {
|
const schema = await this._gristDoc.docComm.fetchTableSchema();
|
||||||
if (!this.isDisposed()) {
|
if (!this.isDisposed()) {
|
||||||
this._schema(schema);
|
this._schema(schema);
|
||||||
|
this._denied(false);
|
||||||
}
|
}
|
||||||
});
|
} catch (err) {
|
||||||
|
if (!String(err).match(/Cannot view code/)) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
if (!this.isDisposed()) {
|
||||||
|
this._schema('');
|
||||||
|
this._denied(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = CodeEditorPanel;
|
module.exports = CodeEditorPanel;
|
||||||
|
@ -658,6 +658,12 @@ export class ActiveDoc extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
public async fetchTableSchema(docSession: DocSession): Promise<string> {
|
public async fetchTableSchema(docSession: DocSession): Promise<string> {
|
||||||
this.logInfo(docSession, "fetchTableSchema(%s)", docSession);
|
this.logInfo(docSession, "fetchTableSchema(%s)", docSession);
|
||||||
|
// Permit code view if user can read everything, or can download/copy (perhaps
|
||||||
|
// via an exceptional permission for sample documents)
|
||||||
|
if (!(await this._granularAccess.canReadEverything(docSession) ||
|
||||||
|
await this.canDownload(docSession))) {
|
||||||
|
throw new ApiError('Cannot view code, it may contain private material', 403);
|
||||||
|
}
|
||||||
await this.waitForInitialization();
|
await this.waitForInitialization();
|
||||||
return this._pyCall('fetch_table_schema');
|
return this._pyCall('fetch_table_schema');
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user