User.coffee 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. class User extends Class
  2. constructor: ->
  3. @data = null
  4. @publickey = null
  5. @data_size = null
  6. @file_rules = null
  7. @loading = false
  8. @inited = false # First load try done
  9. @loaded = new Promise()
  10. @loaded.then (res) =>
  11. @loading = false
  12. @log "Loaded", res
  13. Page.projector.scheduleRender()
  14. getInnerPath: (file_name = "data.json") ->
  15. return "data/users/#{Page.site_info.auth_address}/#{file_name}"
  16. # Find new avalible index
  17. getNewIndex: (node) ->
  18. new_index = Date.now()
  19. for i in [0..100] # Find a free index
  20. if not @data[node][new_index+i]
  21. return new_index+i
  22. getDecryptedSecretsSent: (cb) ->
  23. if not @data?.secrets_sent
  24. cb false
  25. return false
  26. Page.cmd "eciesDecrypt", [@data.secrets_sent], (decrypted) =>
  27. if decrypted
  28. cb JSON.parse(decrypted)
  29. else
  30. cb false
  31. getPublickey: (user_address, cb) ->
  32. Page.cmd "fileGet", {"inner_path": "data/users/#{user_address}/content.json", "required": false}, (res) =>
  33. data = JSON.parse(res)
  34. if data?.publickey
  35. # User's publickey archived to content.json
  36. cb(data.publickey)
  37. else
  38. Page.cmd "fileGet", {"inner_path": "data/users/#{user_address}/data.json", "required": false}, (res) =>
  39. data = JSON.parse(res)
  40. if data?.publickey
  41. cb(data.publickey)
  42. else
  43. Page.users.getArchived (archived) =>
  44. cb(archived[user_address]?["publickey"])
  45. addSecret: (secrets_sent, user_address, cb) ->
  46. @getPublickey user_address, (publickey) =>
  47. if not publickey
  48. cb false
  49. return Page.cmd "wrapperNotification", ["error", "No publickey for user #{user_address}"]
  50. Page.cmd "aesEncrypt", [""], (res) => # Generate new random AES key
  51. [key, iv, encrypted] = res
  52. Page.cmd "eciesEncrypt", [key, publickey], (secret) => # Encrypt the new key for remote user
  53. # Add for remote user
  54. secret_index = @getNewIndex("secret")
  55. @data.secret[secret_index] = secret
  56. # Add key for me
  57. secrets_sent[user_address] = Base64Number.fromNumber(secret_index)+":"+key
  58. Page.cmd "eciesEncrypt", [JSON.stringify(secrets_sent)], (secrets_sent_encrypted) =>
  59. if not secrets_sent_encrypted
  60. return cb false
  61. @data["secrets_sent"] = secrets_sent_encrypted
  62. cb key
  63. getSecret: (user_address, cb) ->
  64. @getDecryptedSecretsSent (secrets_sent) =>
  65. if not secrets_sent
  66. secrets_sent = {}
  67. if secrets_sent[user_address] # Already exits
  68. return cb(secrets_sent[user_address].replace(/.*:/, ""))
  69. else
  70. @log "Creating new secret for #{user_address}"
  71. @addSecret secrets_sent, user_address, (aes_key) ->
  72. cb aes_key
  73. loadData: (cb) ->
  74. inner_path = @getInnerPath()
  75. @log "Loading user file", inner_path
  76. Page.cmd "fileGet", {"inner_path": inner_path, "required": false}, (get_res) =>
  77. if get_res
  78. @data_size = get_res.length
  79. @data = JSON.parse(get_res)
  80. @publickey = @data.publickey
  81. @loaded.resolve()
  82. if cb then cb(true)
  83. @inited = true
  84. Page.projector.scheduleRender()
  85. else
  86. @getPublickey Page.site_info.auth_address, (get_res) =>
  87. if get_res
  88. @publickey = get_res
  89. @data = {"secret": {}, "secrets_sent": "", "publickey": @publickey, "message": {}, "date_added": Date.now()}
  90. @loaded.resolve()
  91. @inited = true
  92. if cb then cb(false)
  93. Page.projector.scheduleRender()
  94. createData: ->
  95. inner_path = @getInnerPath()
  96. @log "Creating user file", inner_path
  97. # First visit, no public key yet
  98. @data = {"secret": {}, "secrets_sent": "", "publickey": null, "message": {}, "date_added": Date.now()}
  99. Page.cmd "userPublickey", [], (publickey_res) =>
  100. if publickey_res.error
  101. Page.cmd "wrapperNotification", ["error", "Publickey read error: #{publickey_res.error}"]
  102. @loaded.fail()
  103. else
  104. @data.publickey = publickey_res
  105. @saveData().then (save_res) =>
  106. @loaded.resolve(save_res)
  107. saveData: (publish=true) ->
  108. promise = new Promise()
  109. inner_path = @getInnerPath()
  110. @data_size = Text.fileEncode(@data).length
  111. Page.cmd "fileWrite", [inner_path, Text.fileEncode(@data)], (write_res) =>
  112. if write_res != "ok"
  113. Page.cmd "wrapperNotification", ["error", "File write error: #{write_res}"]
  114. promise.fail()
  115. return false
  116. Page.cmd "sitePublish", {"inner_path": inner_path}, (publish_res) =>
  117. if publish_res == "ok"
  118. Page.message_lists.sent.reload = true
  119. Page.projector.scheduleRender()
  120. promise.resolve()
  121. else
  122. promise.resolve()
  123. return promise
  124. formatQuota: ->
  125. if not @file_rules
  126. if Page.site_info
  127. @file_rules = {}
  128. Page.cmd "fileRules", @getInnerPath(), (res) =>
  129. @file_rules = res
  130. return " "
  131. else
  132. if @file_rules.max_size
  133. return "#{parseInt(@data_size/1024+1)}k/#{parseInt(@file_rules.max_size/1024)}k"
  134. else
  135. return " "
  136. onSiteInfo: (site_info) ->
  137. if not @loading and site_info.event and site_info.event[0] == "file_done" and site_info.event[1] == @getInnerPath() # User file downloaded
  138. @loadData()
  139. if not @data and not @loading and site_info.cert_user_id and (not site_info.event or site_info.event?[0] == "cert_changed") # Startup or changed user
  140. @loadData()
  141. if not site_info.cert_user_id # Logged out
  142. @data = null
  143. window.User = User