MessageListInbox.coffee 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. class MessageListInbox extends MessageList
  2. constructor: ->
  3. super
  4. @reload = true
  5. @loading = false
  6. @messages = []
  7. @my_aes_keys = {}
  8. @title = "Inbox"
  9. getParsedDb: (cb) ->
  10. Page.on_local_storage.then =>
  11. cb(Page.local_storage.parsed)
  12. decryptKnownAesKeys: (parsed_db, cb) ->
  13. load_keys = ([user_address, secret_id] for user_address, secret_id of parsed_db.my_secret if not @my_aes_keys[user_address])
  14. if load_keys.length > 0
  15. @log "Loading keys", load_keys
  16. where = ("(directory = '#{user_address}' AND date_added = #{secret_id})" for [user_address, secret_id] in load_keys)
  17. query = "SELECT * FROM secret LEFT JOIN json USING (json_id) WHERE #{where.join(' OR ')}"
  18. Page.cmd "dbQuery", query, (rows) =>
  19. Page.cmd "eciesDecrypt", [(row.encrypted for row in rows)], (decrypted_keys) =>
  20. for decrypted_key, i in decrypted_keys
  21. if not decrypted_key then continue
  22. @my_aes_keys[rows[i].directory] = decrypted_key
  23. cb(i)
  24. else
  25. cb(false)
  26. decryptNewSecrets: (parsed_db, cb) ->
  27. parsed_sql = []
  28. known_addresses = []
  29. for user_address, last_parsed of parsed_db.last_secret
  30. parsed_sql.push("(directory = '#{user_address}' AND date_added > #{last_parsed})")
  31. known_addresses.push("'#{user_address}'")
  32. if known_addresses.length > 0
  33. where = "WHERE #{parsed_sql.join(' OR ')} OR directory NOT IN (#{known_addresses.join(",")})"
  34. else
  35. where = ""
  36. query = """
  37. SELECT * FROM secret
  38. LEFT JOIN json USING (json_id)
  39. #{where}
  40. ORDER BY date_added ASC
  41. """
  42. Page.cmd "dbQuery", [query], (db_res) =>
  43. if not db_res.length
  44. cb(false)
  45. return false
  46. secrets = (row.encrypted for row in db_res)
  47. Page.cmd "eciesDecrypt", [secrets], (aes_keys) =>
  48. new_secrets = {}
  49. for aes_key, i in aes_keys
  50. db_row = db_res[i]
  51. if aes_key # Successfully decrypted key, assign it to user
  52. new_secrets[db_row.directory] = db_row.date_added
  53. parsed_db.my_secret[db_row.directory] = db_row.date_added
  54. @my_aes_keys[db_row.directory] = aes_key
  55. # Save last parsed messages id per user
  56. parsed_db.last_secret[db_row.directory] = db_row.date_added
  57. cb(new_secrets)
  58. decryptNewMessages: (parsed_db, new_secrets, cb) ->
  59. parsed_sql = []
  60. for user_address, last_parsed of parsed_db.last_message
  61. parsed_sql.push("(directory = '#{user_address}' AND date_added > #{last_parsed})")
  62. new_addresses = []
  63. for user_address, aes_key of @my_aes_keys
  64. if not parsed_db.last_message[user_address] # Secret shared, but no message parsed yet
  65. new_addresses.push("'#{user_address}'")
  66. if parsed_sql.length > 0
  67. where = "WHERE #{parsed_sql.join(' OR ')} OR directory IN (#{new_addresses.join(",")})"
  68. else
  69. where = "WHERE directory IN (#{new_addresses.join(",")})"
  70. query = """
  71. SELECT * FROM message
  72. LEFT JOIN json USING (json_id)
  73. #{where}
  74. ORDER BY date_added ASC
  75. """
  76. found = 0
  77. Page.cmd "dbQuery", [query], (db_res) =>
  78. if db_res.length == 0
  79. cb(found)
  80. return
  81. aes_keys = (aes_key for address, aes_key of @my_aes_keys)
  82. encrypted_texts = (row.encrypted.split(",") for row in db_res)
  83. Page.cmd "aesDecrypt", [encrypted_texts, aes_keys], (decrypted_texts) =>
  84. for decrypted_text, i in decrypted_texts
  85. db_row = db_res[i]
  86. if not parsed_db.my_message[db_row.directory]
  87. parsed_db.my_message[db_row.directory] = []
  88. if decrypted_text and db_row.date_added not in parsed_db.my_message[db_row.directory]
  89. parsed_db.my_message[db_row.directory].push(db_row.date_added)
  90. found += 1
  91. parsed_db.last_message[db_row.directory] = db_row.date_added
  92. cb(found)
  93. loadMessages: (parsed_db, cb) ->
  94. my_message_ids = []
  95. for address, ids of parsed_db.my_message
  96. my_message_ids = my_message_ids.concat(ids)
  97. query = """
  98. SELECT message.*, json.directory, keyvalue.value AS username FROM message
  99. LEFT JOIN json USING (json_id)
  100. LEFT JOIN json AS json_content ON json_content.directory = json.directory AND json_content.file_name = "content.json"
  101. LEFT JOIN keyvalue ON keyvalue.json_id = json_content.json_id AND keyvalue.key = "cert_user_id"
  102. WHERE date_added IN (#{my_message_ids.join(",")}) AND date_added NOT IN (#{Page.local_storage.deleted.join(",")})
  103. ORDER BY date_added DESC
  104. """
  105. Page.cmd "dbQuery", [query], (db_rows) =>
  106. aes_keys = (aes_key for address, aes_key of @my_aes_keys)
  107. encrypted_messages = (row.encrypted.split(",") for row in db_rows)
  108. Page.cmd "aesDecrypt", [encrypted_messages, aes_keys], (decrypted_messages) =>
  109. message_rows = []
  110. for decrypted_message, i in decrypted_messages
  111. if not decrypted_message then continue
  112. db_row = db_rows[i]
  113. message_row = Text.jsonDecode(decrypted_message)
  114. message_row.date_added = db_row.date_added
  115. message_row.key = "inbox-#{db_row.directory}-#{message_row.date_added}"
  116. message_row.message_id = db_row.date_added
  117. message_row.from = db_row.username
  118. message_row.from_address = db_row.directory
  119. message_row.folder = "inbox"
  120. message_rows.push(message_row)
  121. @syncMessages(message_rows)
  122. Page.projector.scheduleRender()
  123. cb(message_rows)
  124. getMessages: ->
  125. if @reload and Page.site_info
  126. @loading = true
  127. @reload = false
  128. @logStart "getMessages"
  129. Page.on_local_storage.then =>
  130. parsed_db = Page.local_storage.parsed
  131. @decryptKnownAesKeys parsed_db, (loaded_keys) =>
  132. @log "Loaded known AES keys", loaded_keys
  133. @decryptNewSecrets parsed_db, (new_secrets) =>
  134. @log "New secrets found", new_secrets
  135. if not isEmpty(new_secrets)
  136. Page.leftbar.reload_contacts = true
  137. @decryptNewMessages parsed_db, new_secrets, (found) =>
  138. @log "New messages found", found
  139. if not found and @messages.length > 0
  140. @logEnd "getMessages", "No new messages"
  141. Page.local_storage.parsed = parsed_db
  142. @loading = false
  143. @loaded = true
  144. return false
  145. @loadMessages parsed_db, (message_rows) =>
  146. @logEnd "getMessages", "Loaded messages", message_rows.length
  147. Page.local_storage.parsed = parsed_db
  148. Page.saveLocalStorage()
  149. @loading = false
  150. @loaded = true
  151. return @messages
  152. deleteMessage: (message) ->
  153. super
  154. if message.row.message_id not in Page.local_storage.deleted
  155. Page.local_storage.deleted.push(message.row.message_id)
  156. Page.saveLocalStorage()
  157. window.MessageListInbox = MessageListInbox