###############################################################################1#2# CoCalc: Collaborative Calculation in the Cloud3#4# Copyright (C) 2016, Sagemath Inc.5#6# This program is free software: you can redistribute it and/or modify7# it under the terms of the GNU General Public License as published by8# the Free Software Foundation, either version 3 of the License, or9# (at your option) any later version.10#11# This program is distributed in the hope that it will be useful,12# but WITHOUT ANY WARRANTY; without even the implied warranty of13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14# GNU General Public License for more details.15#16# You should have received a copy of the GNU General Public License17# along with this program. If not, see <http://www.gnu.org/licenses/>.18#19###############################################################################2021###22Given a query, do some validation on it, and also possibly fill in fields23in the query that are determined by functional calls in the schema.24If validation fails, this returns an error message; if validation succeeds,25it returns undefined. The input query may be mutated in place.26###2728misc = require('./misc')29schema = require('./schema')3031exports.validate_client_query = validate_client_query = (query, account_id) ->32if misc.is_array(query)33# it's an array of queries; validate each separately.34for q in query35err = validate_client_query(q)36if err?37return err38return3940warn = (err) ->41console.warn("invalid client query: #{err}; query=#{misc.to_json(query)}")42return err4344v = misc.keys(query)45if v.length != 146return warn('must specify exactly one key in the query')47table = v[0]48# Check that the table is in the schema49user_query = schema.SCHEMA[table]?.user_query50if not user_query?51return warn("no user queries of '#{table}' allowed")52pattern = query[table]53if misc.is_array(pattern)54# get queries are an array or a pattern with a null leaf55if pattern.length > 156return warn('array of length > 1 not yet implemented')57pattern = pattern[0]58is_set_query = false59else60# set queries do not have any null leafs61is_set_query = not misc.has_null_leaf(pattern)6263if is_set_query64S = user_query.set65if not S?66return warn("no user set queries of '#{table}' allowed")67else68S = user_query.get69if not S?70return warn("no user get queries of '#{table}' allowed")7172for k,v of pattern73# Verify that every key of the pattern is in the schema74f = S.fields[k]75if f == undefined # crucial: we don't just need "f?" to be true76if is_set_query77return warn("not allowed to set key '#{k}' of '#{table}'")78else79return warn("not allowed to access key '#{k}' of '#{table}'")8081# Fill in any function call parts of the pattern82for k, f of S.fields83if typeof(f) == 'function'84pattern[k] = f(pattern, schema.client_db, account_id)8586if S.required_fields?87for k, v of S.required_fields88if not pattern[k]?89return warn("field '#{k}' must be set")9091return929394