MessageListInbox.coffee 7.7 KB

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