CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/hub/blobs.coffee
Views: 687
1
#########################################################################
2
# This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
# License: MS-RSL – see LICENSE.md for details
4
#########################################################################
5
6
# Blobs
7
8
winston = require('./logger').getLogger('blobs')
9
10
misc_node = require('@cocalc/backend/misc_node')
11
misc = require('@cocalc/util/misc')
12
{defaults, required} = misc
13
{MAX_BLOB_SIZE} = require('@cocalc/util/db-schema/blobs')
14
15
# save a blob in the blobstore database with given misc_node.uuidsha1 hash.
16
exports.save_blob = (opts) ->
17
opts = defaults opts,
18
uuid : undefined # uuid=sha1-based from blob; actually *required*, but instead of a traceback, get opts.cb(err)
19
blob : undefined # actually *required*, but instead of a traceback, get opts.cb(err)
20
ttl : undefined # object in blobstore will have *at least* this ttl in seconds;
21
# if there is already something, in blobstore with longer ttl, we leave it; undefined = infinite ttl
22
check : true # if true, return an error (via cb) if misc_node.uuidsha1(opts.blob) != opts.uuid.
23
# This is a check against bad user-supplied data.
24
project_id : undefined # also required
25
database : required
26
cb : required # cb(err, ttl actually used in seconds); ttl=0 for infinite ttl
27
28
dbg = (m) -> winston.debug("save_blob(uuid=#{opts.uuid}): #{m}")
29
dbg()
30
31
err = undefined
32
33
if not opts.blob?
34
err = "save_blob: UG -- error in call to save_blob (uuid=#{opts.uuid}); received a save_blob request with undefined blob"
35
36
else if not opts.uuid?
37
err = "save_blob: BUG -- error in call to save_blob; received a save_blob request without corresponding uuid"
38
39
else if not opts.project_id?
40
err = "save_blob: BUG -- error in call to save_blob; received a save_blob request without corresponding project_id"
41
42
else if opts.blob.length > MAX_BLOB_SIZE
43
err = "save_blob: blobs are limited to #{misc.human_readable_size(MAX_BLOB_SIZE)} and you just tried to save one of size #{opts.blob.length/1000000}MB"
44
45
else if opts.check and opts.uuid != misc_node.uuidsha1(opts.blob)
46
err = "save_blob: uuid=#{opts.uuid} must be derived from the Sha1 hash of blob, but it is not (possible malicious attack)"
47
48
if err
49
dbg(err)
50
opts.cb(err)
51
return
52
53
# Store the blob in the database, if it isn't there already.
54
opts.database.save_blob
55
uuid : opts.uuid
56
blob : opts.blob
57
ttl : opts.ttl
58
project_id : opts.project_id
59
cb : (err, ttl) =>
60
if err
61
dbg("failed to store blob -- #{err}")
62
else
63
dbg("successfully stored blob")
64
opts.cb(err, ttl)
65
66