You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.0 KiB

Change IDs to strings rather than numbers in API JSON output (#5019) * Fix JavaScript interface with long IDs Somewhat predictably, the JS interface handled IDs as numbers, which in JS are IEEE double-precision floats. This loses some precision when working with numbers as large as those generated by the new ID scheme, so we instead handle them here as strings. This is relatively simple, and doesn't appear to have caused any problems, but should definitely be tested more thoroughly than the built-in tests. Several days of use appear to support this working properly. BREAKING CHANGE: The major(!) change here is that IDs are now returned as strings by the REST endpoints, rather than as integers. In practice, relatively few changes were required to make the existing JS UI work with this change, but it will likely hit API clients pretty hard: it's an entirely different type to consume. (The one API client I tested, Tusky, handles this with no problems, however.) Twitter ran into this issue when introducing Snowflake IDs, and decided to instead introduce an `id_str` field in JSON responses. I have opted to *not* do that, and instead force all IDs to 64-bit integers represented by strings in one go. (I believe Twitter exacerbated their problem by rolling out the changes three times: once for statuses, once for DMs, and once for user IDs, as well as by leaving an integer ID value in JSON. As they said, "If you’re using the `id` field with JSON in a Javascript-related language, there is a very high likelihood that the integers will be silently munged by Javascript interpreters. In most cases, this will result in behavior such as being unable to load or delete a specific direct message, because the ID you're sending to the API is different than the actual identifier associated with the message." [1]) However, given that this is a significant change for API users, alternatives or a transition time may be appropriate. 1: https://blog.twitter.com/developer/en_us/a/2011/direct-messages-going-snowflake-on-sep-30-2011.html * Additional fixes for stringified IDs in JSON These should be the last two. These were identified using eslint to try to identify any plain casts to JavaScript numbers. (Some such casts are legitimate, but these were not.) Adding the following to .eslintrc.yml will identify casts to numbers: ~~~ no-restricted-syntax: - warn - selector: UnaryExpression[operator='+'] > :not(Literal) message: Avoid the use of unary + - selector: CallExpression[callee.name='Number'] message: Casting with Number() may coerce string IDs to numbers ~~~ The remaining three casts appear legitimate: two casts to array indices, one in a server to turn an environment variable into a number. * Back out RelationshipsController Change This was made to make a test a bit less flakey, but has nothing to do with this branch. * Change internal streaming payloads to stringified IDs as well Per https://github.com/tootsuite/mastodon/pull/5019#issuecomment-330736452 we need these changes to send deleted status IDs as strings, not integers.
6 years ago
Change IDs to strings rather than numbers in API JSON output (#5019) * Fix JavaScript interface with long IDs Somewhat predictably, the JS interface handled IDs as numbers, which in JS are IEEE double-precision floats. This loses some precision when working with numbers as large as those generated by the new ID scheme, so we instead handle them here as strings. This is relatively simple, and doesn't appear to have caused any problems, but should definitely be tested more thoroughly than the built-in tests. Several days of use appear to support this working properly. BREAKING CHANGE: The major(!) change here is that IDs are now returned as strings by the REST endpoints, rather than as integers. In practice, relatively few changes were required to make the existing JS UI work with this change, but it will likely hit API clients pretty hard: it's an entirely different type to consume. (The one API client I tested, Tusky, handles this with no problems, however.) Twitter ran into this issue when introducing Snowflake IDs, and decided to instead introduce an `id_str` field in JSON responses. I have opted to *not* do that, and instead force all IDs to 64-bit integers represented by strings in one go. (I believe Twitter exacerbated their problem by rolling out the changes three times: once for statuses, once for DMs, and once for user IDs, as well as by leaving an integer ID value in JSON. As they said, "If you’re using the `id` field with JSON in a Javascript-related language, there is a very high likelihood that the integers will be silently munged by Javascript interpreters. In most cases, this will result in behavior such as being unable to load or delete a specific direct message, because the ID you're sending to the API is different than the actual identifier associated with the message." [1]) However, given that this is a significant change for API users, alternatives or a transition time may be appropriate. 1: https://blog.twitter.com/developer/en_us/a/2011/direct-messages-going-snowflake-on-sep-30-2011.html * Additional fixes for stringified IDs in JSON These should be the last two. These were identified using eslint to try to identify any plain casts to JavaScript numbers. (Some such casts are legitimate, but these were not.) Adding the following to .eslintrc.yml will identify casts to numbers: ~~~ no-restricted-syntax: - warn - selector: UnaryExpression[operator='+'] > :not(Literal) message: Avoid the use of unary + - selector: CallExpression[callee.name='Number'] message: Casting with Number() may coerce string IDs to numbers ~~~ The remaining three casts appear legitimate: two casts to array indices, one in a server to turn an environment variable into a number. * Back out RelationshipsController Change This was made to make a test a bit less flakey, but has nothing to do with this branch. * Change internal streaming payloads to stringified IDs as well Per https://github.com/tootsuite/mastodon/pull/5019#issuecomment-330736452 we need these changes to send deleted status IDs as strings, not integers.
6 years ago
Change IDs to strings rather than numbers in API JSON output (#5019) * Fix JavaScript interface with long IDs Somewhat predictably, the JS interface handled IDs as numbers, which in JS are IEEE double-precision floats. This loses some precision when working with numbers as large as those generated by the new ID scheme, so we instead handle them here as strings. This is relatively simple, and doesn't appear to have caused any problems, but should definitely be tested more thoroughly than the built-in tests. Several days of use appear to support this working properly. BREAKING CHANGE: The major(!) change here is that IDs are now returned as strings by the REST endpoints, rather than as integers. In practice, relatively few changes were required to make the existing JS UI work with this change, but it will likely hit API clients pretty hard: it's an entirely different type to consume. (The one API client I tested, Tusky, handles this with no problems, however.) Twitter ran into this issue when introducing Snowflake IDs, and decided to instead introduce an `id_str` field in JSON responses. I have opted to *not* do that, and instead force all IDs to 64-bit integers represented by strings in one go. (I believe Twitter exacerbated their problem by rolling out the changes three times: once for statuses, once for DMs, and once for user IDs, as well as by leaving an integer ID value in JSON. As they said, "If you’re using the `id` field with JSON in a Javascript-related language, there is a very high likelihood that the integers will be silently munged by Javascript interpreters. In most cases, this will result in behavior such as being unable to load or delete a specific direct message, because the ID you're sending to the API is different than the actual identifier associated with the message." [1]) However, given that this is a significant change for API users, alternatives or a transition time may be appropriate. 1: https://blog.twitter.com/developer/en_us/a/2011/direct-messages-going-snowflake-on-sep-30-2011.html * Additional fixes for stringified IDs in JSON These should be the last two. These were identified using eslint to try to identify any plain casts to JavaScript numbers. (Some such casts are legitimate, but these were not.) Adding the following to .eslintrc.yml will identify casts to numbers: ~~~ no-restricted-syntax: - warn - selector: UnaryExpression[operator='+'] > :not(Literal) message: Avoid the use of unary + - selector: CallExpression[callee.name='Number'] message: Casting with Number() may coerce string IDs to numbers ~~~ The remaining three casts appear legitimate: two casts to array indices, one in a server to turn an environment variable into a number. * Back out RelationshipsController Change This was made to make a test a bit less flakey, but has nothing to do with this branch. * Change internal streaming payloads to stringified IDs as well Per https://github.com/tootsuite/mastodon/pull/5019#issuecomment-330736452 we need these changes to send deleted status IDs as strings, not integers.
6 years ago
Change IDs to strings rather than numbers in API JSON output (#5019) * Fix JavaScript interface with long IDs Somewhat predictably, the JS interface handled IDs as numbers, which in JS are IEEE double-precision floats. This loses some precision when working with numbers as large as those generated by the new ID scheme, so we instead handle them here as strings. This is relatively simple, and doesn't appear to have caused any problems, but should definitely be tested more thoroughly than the built-in tests. Several days of use appear to support this working properly. BREAKING CHANGE: The major(!) change here is that IDs are now returned as strings by the REST endpoints, rather than as integers. In practice, relatively few changes were required to make the existing JS UI work with this change, but it will likely hit API clients pretty hard: it's an entirely different type to consume. (The one API client I tested, Tusky, handles this with no problems, however.) Twitter ran into this issue when introducing Snowflake IDs, and decided to instead introduce an `id_str` field in JSON responses. I have opted to *not* do that, and instead force all IDs to 64-bit integers represented by strings in one go. (I believe Twitter exacerbated their problem by rolling out the changes three times: once for statuses, once for DMs, and once for user IDs, as well as by leaving an integer ID value in JSON. As they said, "If you’re using the `id` field with JSON in a Javascript-related language, there is a very high likelihood that the integers will be silently munged by Javascript interpreters. In most cases, this will result in behavior such as being unable to load or delete a specific direct message, because the ID you're sending to the API is different than the actual identifier associated with the message." [1]) However, given that this is a significant change for API users, alternatives or a transition time may be appropriate. 1: https://blog.twitter.com/developer/en_us/a/2011/direct-messages-going-snowflake-on-sep-30-2011.html * Additional fixes for stringified IDs in JSON These should be the last two. These were identified using eslint to try to identify any plain casts to JavaScript numbers. (Some such casts are legitimate, but these were not.) Adding the following to .eslintrc.yml will identify casts to numbers: ~~~ no-restricted-syntax: - warn - selector: UnaryExpression[operator='+'] > :not(Literal) message: Avoid the use of unary + - selector: CallExpression[callee.name='Number'] message: Casting with Number() may coerce string IDs to numbers ~~~ The remaining three casts appear legitimate: two casts to array indices, one in a server to turn an environment variable into a number. * Back out RelationshipsController Change This was made to make a test a bit less flakey, but has nothing to do with this branch. * Change internal streaming payloads to stringified IDs as well Per https://github.com/tootsuite/mastodon/pull/5019#issuecomment-330736452 we need these changes to send deleted status IDs as strings, not integers.
6 years ago
  1. # frozen_string_literal: true
  2. class REST::StatusSerializer < ActiveModel::Serializer
  3. attributes :id, :created_at, :in_reply_to_id, :in_reply_to_account_id,
  4. :sensitive, :spoiler_text, :visibility, :language,
  5. :uri, :url, :replies_count, :reblogs_count,
  6. :favourites_count
  7. attribute :favourited, if: :current_user?
  8. attribute :reblogged, if: :current_user?
  9. attribute :muted, if: :current_user?
  10. attribute :bookmarked, if: :current_user?
  11. attribute :pinned, if: :pinnable?
  12. attribute :content, unless: :source_requested?
  13. attribute :text, if: :source_requested?
  14. belongs_to :reblog, serializer: REST::StatusSerializer
  15. belongs_to :application, if: :show_application?
  16. belongs_to :account, serializer: REST::AccountSerializer
  17. has_many :media_attachments, serializer: REST::MediaAttachmentSerializer
  18. has_many :ordered_mentions, key: :mentions
  19. has_many :tags
  20. has_many :emojis, serializer: REST::CustomEmojiSerializer
  21. has_one :preview_card, key: :card, serializer: REST::PreviewCardSerializer
  22. has_one :preloadable_poll, key: :poll, serializer: REST::PollSerializer
  23. def id
  24. object.id.to_s
  25. end
  26. def in_reply_to_id
  27. object.in_reply_to_id&.to_s
  28. end
  29. def in_reply_to_account_id
  30. object.in_reply_to_account_id&.to_s
  31. end
  32. def current_user?
  33. !current_user.nil?
  34. end
  35. def show_application?
  36. object.account.user_shows_application? || (current_user? && current_user.account_id == object.account_id)
  37. end
  38. def visibility
  39. # This visibility is masked behind "private"
  40. # to avoid API changes because there are no
  41. # UX differences
  42. if object.limited_visibility?
  43. 'private'
  44. else
  45. object.visibility
  46. end
  47. end
  48. def sensitive
  49. if current_user? && current_user.account_id == object.account_id
  50. object.sensitive
  51. else
  52. object.account.sensitized? || object.sensitive
  53. end
  54. end
  55. def uri
  56. ActivityPub::TagManager.instance.uri_for(object)
  57. end
  58. def content
  59. Formatter.instance.format(object)
  60. end
  61. def url
  62. ActivityPub::TagManager.instance.url_for(object)
  63. end
  64. def favourited
  65. if instance_options && instance_options[:relationships]
  66. instance_options[:relationships].favourites_map[object.id] || false
  67. else
  68. current_user.account.favourited?(object)
  69. end
  70. end
  71. def reblogged
  72. if instance_options && instance_options[:relationships]
  73. instance_options[:relationships].reblogs_map[object.id] || false
  74. else
  75. current_user.account.reblogged?(object)
  76. end
  77. end
  78. def muted
  79. if instance_options && instance_options[:relationships]
  80. instance_options[:relationships].mutes_map[object.conversation_id] || false
  81. else
  82. current_user.account.muting_conversation?(object.conversation)
  83. end
  84. end
  85. def bookmarked
  86. if instance_options && instance_options[:relationships]
  87. instance_options[:relationships].bookmarks_map[object.id] || false
  88. else
  89. current_user.account.bookmarked?(object)
  90. end
  91. end
  92. def pinned
  93. if instance_options && instance_options[:relationships]
  94. instance_options[:relationships].pins_map[object.id] || false
  95. else
  96. current_user.account.pinned?(object)
  97. end
  98. end
  99. def pinnable?
  100. current_user? &&
  101. current_user.account_id == object.account_id &&
  102. !object.reblog? &&
  103. %w(public unlisted).include?(object.visibility)
  104. end
  105. def source_requested?
  106. instance_options[:source_requested]
  107. end
  108. def ordered_mentions
  109. object.active_mentions.to_a.sort_by(&:id)
  110. end
  111. class ApplicationSerializer < ActiveModel::Serializer
  112. attributes :name, :website
  113. end
  114. class MentionSerializer < ActiveModel::Serializer
  115. attributes :id, :username, :url, :acct
  116. def id
  117. object.account_id.to_s
  118. end
  119. def username
  120. object.account_username
  121. end
  122. def url
  123. ActivityPub::TagManager.instance.url_for(object.account)
  124. end
  125. def acct
  126. object.account.pretty_acct
  127. end
  128. end
  129. class TagSerializer < ActiveModel::Serializer
  130. include RoutingHelper
  131. attributes :name, :url
  132. def url
  133. tag_url(object)
  134. end
  135. end
  136. end