Compare commits

...

629 Commits

Author SHA1 Message Date
Eugen Rochko
07d93716aa Improve remote profile disclaimer (#4342)
* Improve remote profile disclaimer

* yarn run manage:translations
2017-07-24 20:05:29 +02:00
Eugen Rochko
88b5e0b703 Use the "m" version of the logo for favicons (#4345) 2017-07-24 19:54:59 +02:00
Sorin Davidoi
32fa312b2a fix(compose_from): Do not autofocus on mobile (#4344) 2017-07-24 19:54:39 +02:00
Eugen Rochko
1306d637a2 Fix oddities with public profile CSS (#4341)
* Fix oddities with public profile CSS

* Remove trailing whitespace
2017-07-24 17:56:50 +02:00
m4sk1n
462b3752e4 i18n: @2374d63 (pl) (#4340)
* i18n: @2374d63 (pl)

* i18n: fixed typo on Polish translation
2017-07-24 17:15:35 +02:00
Eugen Rochko
029f2c4545 Redesign /terms page (#4338)
* Redesign /terms page

* Fix tests

* Remove unused keys
2017-07-24 17:15:15 +02:00
Lynx Kotoura
b3e7beb7c5 Perfectly center mastodon logo on mobile landing page (#4339)
Setting only padding-left made the logo left-shifted on mobile page. Margin-right was old setting for adjusting clearance between old logo and letter "Mastodon".
2017-07-24 16:52:47 +02:00
Eugen Rochko
a549d1ae6b Bump to 1.5.0rc1 (#4318) 2017-07-24 16:21:08 +02:00
Eugen Rochko
467456f7a1 Move clean up of unconfirmed users to sidekiq-scheduler (#4336)
* Move clean up of unconfirmed users to sidekiq-scheduler

* mastodon:daily is now deprecated
2017-07-24 16:17:55 +02:00
Eugen Rochko
2374d63536 Redesign extended information page (#4322)
* Redesign extended information page

* Remove unused keys

* Add $ui-base-lighter-color variable to SCSS
2017-07-24 15:09:08 +02:00
Yamagishi Kazutoshi
117eb3b2bc Change defaultMessage for spoiler placeholder (#4329) 2017-07-24 14:49:06 +02:00
Eugen Rochko
de985a30bc Run i18n-tasks normalize (#4335) 2017-07-24 14:30:10 +02:00
sdukhovni
06d905f415 Allow domain blocks that only reject media without silencing or suspending (#4325)
* Allow domain blocks to reject media without silencing or suspending

* Fix typo

* Hide 'Reject media' button when superfluous, instead of disabling it

* Properly hide 'reject media' checkbox on page load if needed

This may happen when resubmitting the domain block form after an error.

* Don't ask whether undoing a media-only block should be retroactive

* Rename :media_only block to :noop

* Display :noop block as None in frontend, allow blocks that do nothing

* Remove 'coding' line auto-added by emacs
2017-07-24 14:26:55 +02:00
Andrew Zyabin
0ad41be0f3 Update Russian translation for #4313 (#4334) 2017-07-24 13:37:05 +02:00
masarakki
d6f5dbff3e add-dependent-package (#4330) 2017-07-24 10:51:38 +02:00
Yamagishi Kazutoshi
1e665a0bf4 Add space to toot paragraph in landing page (#4331) 2017-07-24 10:43:59 +02:00
Yamagishi Kazutoshi
ef16089c6d Redirect user profile page to short URL when HTML format (#4328) 2017-07-24 08:46:29 +02:00
m4sk1n
4b4ea1f929 i18n: Update Polish translation (#4327)
* i18n: Update Polish translation

* i18n: Update Polish translation
2017-07-23 23:57:13 +02:00
Yamagishi Kazutoshi
45af29912f Change about_mastodon to about_mastodon_html for all locales (#4326) 2017-07-23 23:32:53 +02:00
Sorin Davidoi
9075c90c46 feat: Enable push subscription for mobile devices by default (#4321) 2017-07-23 23:27:23 +02:00
Yamagishi Kazutoshi
63a2566007 Fix manifest description (regression from #4122) (#4324) 2017-07-23 23:04:44 +02:00
Yamagishi Kazutoshi
43cad817e8 Update Japanese translations for #4313 and #4315 (#4323)
* Update Japanese translations for #4313

* Update Japanese translations for #4315
2017-07-23 23:04:25 +02:00
Eugen Rochko
ed4c754fff Add background to media modal (#4317) 2017-07-23 20:28:31 +02:00
Eugen Rochko
1e0c7a0afc Add loading indicator animation (#4316) 2017-07-23 20:28:18 +02:00
Eugen Rochko
3a3b556065 Improve noscript message and style (#4315) 2017-07-23 20:28:06 +02:00
Sylvhem
9244f6b628 Change "Content Warning" to "Write your warning here" (#4313)
Change the placeholder used in the content warning field from "Content Warning" to "Write your warning here". This change should made it easier to understand what the field is about.

Change le message de substitution utilisé dans le champ d’avertissement de « Avertissement » à « Écrivez ici votre avertissement ». Ce changement devrait rendre plus évidente la fonction du champ.
2017-07-23 16:57:32 +02:00
Sorin Davidoi
ff26b72333 fix(getting_started): Scroll on mobile (#4312) 2017-07-23 14:50:26 +02:00
m4sk1n
6803935c4d i18n: Update Polish translation (#4311) 2017-07-23 14:50:10 +02:00
Sorin Davidoi
3757546f1b fix(columns_area): Show correct title for preview columns (#4310) 2017-07-23 14:03:35 +02:00
Quent-in
a677ac8384 i10n Update for Occitan (#4301)
* Update to translate new strings

* Update

* Update

* Indend added

* Update oc.yml
2017-07-23 12:46:40 +02:00
Yamagishi Kazutoshi
bdbfb10cff Fix logo URL (#4309) 2017-07-23 12:46:10 +02:00
Yamagishi Kazutoshi
4d661e1183 Change logo.png to logo.svg for web UI (#4307) 2017-07-23 11:09:42 +02:00
Eugen Rochko
dd28b557ae Update README header with logo 2017-07-23 02:46:10 +02:00
Eugen Rochko
0e0f18ce7c New logo (#4306)
* Add new logo

* Remove unused images
2017-07-23 02:40:39 +02:00
Eugen Rochko
7964bfccdb Add rake task mastodon:feeds:build to regenerate all active users' feeds (#4303) 2017-07-23 01:15:04 +02:00
Eugen Rochko
3c515f2cd2 Run yarn run manage:translations and i18n-tasks normalize (#4302) 2017-07-23 01:14:57 +02:00
Ondřej Hruška
db73ac92d7 Changed landing page cloud animation to be more relaxed and smoother (#4304) 2017-07-22 22:27:06 +02:00
Damien Erambert
4cd82d442e Update French locales (settings, ToS, & co) (#4261)
* add fr-FR locales to the landing page

* moar french locales

* terms of service/privacy policy

* remove un-used locales in the client (yarn manage:translations)

* update french locales in the client

* remove duplicate locales in fr.yml

* fix typos per PR comments in fr.yml

* put back default messages

* translate untranslated keys on the client

* add "push" after notifications

* correctly ident ToS in fr.yml
2017-07-22 20:28:40 +02:00
Eugen Rochko
311871eefc Turn clouds on landing page into SVGs, use SCSS variables to color them (#4299) 2017-07-22 16:36:54 +02:00
Eugen Rochko
a929f7e6ac Fix #4172 - Mutes now block notifications (#4300) 2017-07-22 16:36:36 +02:00
Sylvhem
cf51e07bde Mise à jour de la traduction de la page d’accueil (#4294)
* Mise à jour de la traduction de la page d’accueil

Met à jour les traductions et ajoute les chaînes manquantes suite à la refonte de la page d’accueil.

Update translations and add the strings introduced by the landing page's redesign.

* Correction d’erreurs

Corrige l’indentation de certaines clefs et supprime admin.settings.setting qui n’existe plus dans le projet original.

Fix some indentations and delete admin.settings.setting, which have been removed upstream.
2017-07-22 14:11:46 +02:00
Eugen Rochko
8d6c3cd48a Fix sessions being replaced needlessly (#4292) 2017-07-22 01:09:10 +02:00
Sorin Davidoi
3817704806 feat(compose): Change media query for compact mode to max-height: 400px (#4291) 2017-07-21 14:22:29 +02:00
Yamagishi Kazutoshi
d4c6bf770d Run bundle (regression from #4284) (#4290) 2017-07-21 14:22:05 +02:00
Eugen Rochko
399f9f4a4e Update Goldfinger gem to 2.0 (#4286)
- No masking of HTTP::Error and OpenSSL::SSL::SSLError
- No longer accepts non-HTTPS WebFinger endpoints
2017-07-21 13:40:48 +02:00
Yamagishi Kazutoshi
f2390e2803 Dynamicaly change avatar and header bg from account setting (#4289) 2017-07-21 12:47:16 +02:00
Eugen Rochko
dbaa6a0e13 Fix intermittent test failures due to accidentally reused class instance between threads (#4287) 2017-07-21 12:45:13 +02:00
Eugen Rochko
7bf7ed6123 Fix #3220 - Show avatar/header on edit profile page (#4288) 2017-07-21 05:28:51 +02:00
Eugen Rochko
a390abdefb Use the same emoji data on the frontend and backend (#4284)
* Use the same emoji data on the frontend and backend

* Move emoji.json to repository, add tests

This way you don't need to install node dependencies if you only
want to run Ruby code
2017-07-21 04:27:40 +02:00
Sorin Davidoi
c1bc5e14eb feat(compose): More space on mobile devices (#4282)
* feat(compose): More space on mobile devices

* feat(compose): Hide navigation when typing on mobile devices

* fix(compose): Make animation faster

* fix(navigation_bar): Remove hardcoded title

* fix(compose): Prevent accidental bluring

* fix(compose): Increase max-height to 600px
2017-07-21 01:38:24 +02:00
Eugen Rochko
4b911fea03 Add button to re-subscribe to all accounts from a domain (#4285) 2017-07-20 23:07:13 +02:00
Eugen Rochko
1fcdaafa6f Fix webfinger retries (#4275)
* Do not raise unretryable exceptions in ResolveRemoteAccountService

* Removed fatal exceptions from ResolveRemoteAccountService

Exceptions that cannot be retried should not be raised. New exception
class for those that can be retried (Mastodon::UnexpectedResponseError)
2017-07-20 01:59:07 +02:00
Sorin Davidoi
f24b81e27f feat(css): Remove border radius from WebKit's scrollbars (#4278) 2017-07-20 00:20:54 +02:00
Sorin Davidoi
e01966f7b8 fix(status_list): Update scroll position after toots are appended (#4277) 2017-07-19 22:38:26 +02:00
Sorin Davidoi
dcb9497148 fix(push_subscription): Guard against malformed favourite notification (#4271) 2017-07-19 22:37:52 +02:00
unarist
4f2513337f Update scroll top state on column mounting (#4276) 2017-07-19 20:26:51 +02:00
Sorin Davidoi
015269914e fix: Handle errors without response (#4274) 2017-07-19 19:38:50 +02:00
Eugen Rochko
bbdcfd6baf Add ActivityPub attributes to accounts (#4273) 2017-07-19 17:06:46 +02:00
Akihiko Odaki
f0d6550f16 Fix logging in ProcessFeedService (#4270) 2017-07-19 16:02:03 +02:00
Eugen Rochko
8400bee3b1 Refactor ResolveRemoteAccountService (#4258)
* Refactor ResolveRemoteAccountService

* Remove trailing whitespace

* Use redis locks around critical ResolveRemoteAccountService code

* Add test for race condition of lock
2017-07-19 14:44:04 +02:00
Cygnan
bc1f9dc24b Fix a typo in public.js (double semicolons) (#4269)
Signed-off-by: Cygnan <mail@cygnan.com>
2017-07-19 13:35:22 +02:00
m4sk1n
cdc349a2d1 i18n: Update Polish translation (#4268) 2017-07-19 12:25:06 +02:00
Eugen Rochko
c2c93f8cd6 Fix deprecation warning for non-pipeline assets (#4267) 2017-07-19 12:00:05 +02:00
m4sk1n
9fc082ea81 i18n: @716f4cb (pl) (#4266)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-19 10:49:36 +02:00
Damien Erambert
4c7a9adb98 fix missing closing <p> tag in ToS in en.yml (#4262) 2017-07-19 09:43:46 +02:00
m4sk1n
030e5cec58 Fix missing closing <p> tag in ToS in .yml files (#4264)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-19 09:43:10 +02:00
Yamagishi Kazutoshi
716f4cb11c Add feature to revoke sessions (#4259) 2017-07-19 04:59:04 +02:00
Eugen Rochko
a5a07da892 Correct OStatus inflection (Ostatus -> OStatus) (#4255) 2017-07-19 01:37:26 +02:00
Sorin Davidoi
72108b20e2 feat(emoji): Add back title attribute (#4253) 2017-07-18 22:49:24 +02:00
lindwurm
767117f9b0 Update Japanese translation (chase #4249) (#4251)
Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-07-18 20:03:18 +02:00
m4sk1n
fb7f06a752 i18n: Update Polish translation (#4252)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-18 20:03:06 +02:00
lindwurm
0b4006fc47 Add Japanese translation for #4246 (#4249)
Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-07-18 18:43:19 +02:00
lindwurm
0ccd47f413 Update Japanese translations for new landing page (#4159)
Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-07-18 18:42:59 +02:00
Ondřej Hruška
02f896c12e Fix broken CSS reload due to webpack upgrade (#4250) 2017-07-18 18:42:45 +02:00
unarist
bb4c3831b2 Add Japanese translation for #4199 (#4247) 2017-07-18 17:23:35 +02:00
Yamagishi Kazutoshi
3267e4a785 Add unfollow modal (optional) (#4246)
* Add unfollow modal

* unfollowing someone

* remove unnecessary prop
2017-07-18 17:14:43 +02:00
Akihiko Odaki
89b988cab5 Introduce Ostatus name space (#4164)
* Wrap methods of ProcessFeedService::ProcessEntry in classes

This is a change same with 425acecfdb, except
that it has the following changes:

* Revert irrelevant change in find_or_create_conversation
* Fix error handling for RemoteActivity

* Introduce Ostatus name space
2017-07-18 16:39:47 +02:00
abcang
4d42a38954 Improve admin page (#4121)
* Improve admin page

* Fix test

* Add spec

* Improve select style
2017-07-18 16:38:22 +02:00
Sorin Davidoi
8387b3928e fix(push-subscriptions): Refactor how Sidekiq jobs are handled (#4226) 2017-07-18 16:25:40 +02:00
abcang
afa52e4d63 Fixed issue that the NSFW image is not hidden on detail page (#4244) 2017-07-18 15:24:57 +02:00
Yamagishi Kazutoshi
8949aad030 Add empty alt attribute to img elements in landing page (#4243) 2017-07-18 15:22:09 +02:00
Yamagishi Kazutoshi
c0c7af2194 Download npm and yarn from Alpine packages repository (#4242) 2017-07-18 15:21:30 +02:00
Yamagishi Kazutoshi
f5382ec085 Exclude self toots from regular expression filter (#4245)
* Exclude self toots from regular expression filter

* refactor
2017-07-18 15:20:38 +02:00
Yamagishi Kazutoshi
407073d7a2 Move icu-dev to build-dependencies (#4240) 2017-07-18 15:19:49 +02:00
Yamagishi Kazutoshi
7f4375822a Install libidn11-dev in Vagrant (#4238) 2017-07-18 00:31:43 +02:00
Sorin Davidoi
719ab720a7 feat(push-notifications): Open link in current tab if possible (#4228)
* fix(push-notification): Open link in current tab if possible

* feat(sw): Skip waiting and claim clients
2017-07-18 00:19:17 +02:00
Akihiko Odaki
b11ac88692 Require any modules after loading polyfill in entry points (#4231)
app/javascript/mastodon/main.js delayed the execution of modules,
but other entry points didn't. That leads to failure in executing
modules, which requires those polyfills.

Strictly enforce the rule to require any modules after loading
polyfill in entry points.
2017-07-18 00:19:02 +02:00
Lynx Kotoura
681c33d1f4 Quit overwriting style of extended-video-player (#4237)
Though size of extended-video-player is already fixed to 80vw*80vh in components.scss, player size was also set to original video size in extended_video_player.js. Video size is fixed to 80vw*80vh, so video player's size must also be fixed to 80vw*80vh.
2017-07-17 19:05:29 +02:00
Akihiko Odaki
7f35947d8e Improve a query in WebPushNotificationWorker (#4234) 2017-07-17 11:03:48 +02:00
Akihiko Odaki
68941d4dfa Use update method to update session in WebPushNotificationWorker (#4235) 2017-07-17 11:03:42 +02:00
Sorin Davidoi
1d2616b79b fix(emojis): Handle multipoint emojis (e.g. country flags) (#4221) 2017-07-17 10:57:45 +02:00
Eugen Rochko
d4b097a88c Add missing ActivityPub representations (#4230)
- Follow, undo follow
- Accept follow, reject follow
- Like, undo like
- Block, undo block
- Delete (note)
- Update (actor)
2017-07-17 10:57:04 +02:00
m4sk1n
902c5cf7ca i18n: update (pl) (#4233)
* i18n: update (pl)

* Update pl.yml
2017-07-17 10:24:53 +02:00
Akihiko Odaki
b15f790221 Require images in common.js (#4232) 2017-07-17 10:23:28 +02:00
Eugen Rochko
a47c2e8890 Add public key declaration to actors (#4215) 2017-07-17 02:37:27 +02:00
Eugen Rochko
a3202fd51e Add SMTP_TLS variable for configuring TLS when server uses non-standard port (#4227) 2017-07-16 23:48:35 +02:00
unarist
1cceefce33 Check table existence on prepare_for_foreign_keys (#4225)
* Check table existence on prepare_for_foreign_keys

* Remove trailing whitespace
2017-07-16 20:01:21 +02:00
unarist
033f970af3 Don't mention default post privacy on hints for locked accounts (#4222)
"defaults post privacy to followers-only" only means...

* default value of `visibility` param on post API
* default value for web UI privacy setting (i.e. it will be overridden if they once updated)

...so, many users won't see an effect of it.
2017-07-16 14:02:03 +02:00
Lynx Kotoura
d1c3e35d3f Fix style settings for images in media modal (#4220)
* Shrink too wide single image modal

Fix too wide react-swipeable-view-container

Fix 0067f80 shrinking all react-swipeable-view-container

Change to apply max-width of react-swipeable-view-container only under media-modal.

Fix b30b03b just a typo

* Centering contents in image-loader

Centering small img, canvas, and video in image-loader.
2017-07-16 11:52:11 +02:00
Eugen Rochko
a6328fc1b1 Minor ActivityPub JSON fixes (#4214)
- Objects must have attributedTo instead of actor
- The current attribute belongs to CollectionPage, not Collection
2017-07-16 10:28:55 +02:00
Yamagishi Kazutoshi
35b868eeca Install libidn with Docker (#4219) 2017-07-16 04:40:56 +02:00
unarist
695439775e Fix column swiping (#4211)
This fixes broken behavior and enable animation only on swiping.
2017-07-15 17:25:04 +02:00
ThibG
05cd37097c Optimize uri normalization (#4212)
* Add dependency on idn-ruby to speed up URI normalization

* Use normalized_host instead of normalize.host when applicable

When we are only interested in the normalized host, calling normalized_host
avoids normalizing the other components of the URI as well as creating a
new object
2017-07-15 17:24:35 +02:00
Yamagishi Kazutoshi
bd915d9398 Move babel-plugin-preval to dependencies (#4209) 2017-07-15 12:47:43 +02:00
Eugen Rochko
8c45cd0e36 Improve ActivityPub representations (#3844)
* Improve webfinger templates and make tests more flexible

* Clean up AS2 representation of actor

* Refactor outbox

* Create activities representation

* Add representations of followers/following collections, do not redirect /users/:username route if format is empty

* Remove unused translations

* ActivityPub endpoint for single statuses, add ActivityPub::TagManager for better
URL/URI generation

* Add ActivityPub::TagManager#to

* Represent all attachments as Document instead of Image/Video specifically
(Because for remote ones we may not know for sure)

Add mentions and hashtags representation to AP notes

* Add AP-resolvable hashtag URIs

* Use ActiveModelSerializers for ActivityPub

* Clean up unused translations

* Separate route for object and activity

* Adjust cc/to matrices

* Add to/cc to activities, ensure announce activity embeds target status and
not the wrapper status, add "id" to all collections
2017-07-15 03:01:39 +02:00
Eugen Rochko
3fbf1bf35a Fix #3773 - Pin favourites column (#4201) 2017-07-15 00:49:34 +02:00
Eugen Rochko
cd9b2ab2f7 Fix #2672 - Connect signed PuSH subscription requests to instance domain (#4205)
* Fix #2672 - Connect signed PuSH subscription requests to instance domain

Resolves #2739

* Fix return of locate_subscription

* Fix tests
2017-07-14 23:01:20 +02:00
Eugen Rochko
de397f3bc1 Fix subsequent replies to unresolved status not being filtered from home (#4190)
Resolves #4177 - smaller changeset
2017-07-14 22:31:38 +02:00
Sorin Davidoi
72bd73f605 Small style fixes (#4206)
* fix(components/media_modal): Center horizontally in Firefox

* fix(components/status_list): Do not remove load more button
2017-07-14 22:31:25 +02:00
unarist
1896a154f5 Fix response of unreblog/unfavourite APIs (#4204)
Both APIs process asynchronously, so reblogged/favourited fields in the response should be set to `false` manually.
2017-07-14 20:44:53 +02:00
Eugen Rochko
1618b68bfa HTTP signatures (#4146)
* Add Request class with HTTP signature generator

Spec: https://tools.ietf.org/html/draft-cavage-http-signatures-06

* Add HTTP signature verification concern

* Add test for SignatureVerification concern

* Add basic test for Request class

* Make PuSH subscribe/unsubscribe requests use new Request class

Accidentally fix lease_seconds not being set and sent properly, and
change the new minimum subscription duration to 1 day

* Make all PuSH workers use new Request class

* Make Salmon sender use new Request class

* Make FetchLinkService use new Request class

* Make FetchAtomService use the new Request class

* Make Remotable use the new Request class

* Make ResolveRemoteAccountService use the new Request class

* Add more tests

* Allow +-30 seconds window for signed request to remain valid

* Disable time window validation for signed requests, restore 7 days
as PuSH subscription duration (which was previous default due to a bug)
2017-07-14 20:41:49 +02:00
Sorin Davidoi
c1f201c49a 🎄🔨 Force tree shake emojione (#4202)
* chore(yarn): Install babel-plugin-preval as development dependency

* feat(babel): Add preval as a plugin

* feat(emojione_light): Prevaled module what tree-shaked emojione

* refactor(emoji): Use emojione_light

* feat: Preload emojione_picker bundle

* fix(emojione_light): Do not use Object.entries

* fix(emojify): Update tests

* chore(emojione_light): Remove silly ascii art
2017-07-14 20:30:12 +02:00
unarist
8d224ad23b Follow renaming of microformats2 gem (#4203) 2017-07-14 19:57:49 +02:00
Eugen Rochko
e2685ccc81 Fix #4149, fix #1199 - Store emojis as unicode (#4189)
- Use unicode when selecting emoji through picker
- Convert shortcodes to unicode when storing text input server-side
- Do not convert shortcodes in JS anymore
2017-07-14 19:47:53 +02:00
Eugen Rochko
c42092ba7a Add option to opt out of search engines on public profile/status pages (#4199) 2017-07-14 16:41:02 +02:00
m4sk1n
999170d898 i18n: fediwers › fediwersum (pl) (#4198)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-14 14:41:13 +02:00
Albert ARIBAUD
37430a3401 fr: replace "silencer" with "masquer" throughout (#4197)
* fr.json: replace "silencer" with "masquer"

"Silencer" as a verb does not exist in French. A good and valid replacement is "masquer".

* FR translation: use "masquer" for "silence"
2017-07-14 13:55:40 +02:00
Yamagishi Kazutoshi
0fa9dd8527 Add Rake task for generate VAPID key (#4195)
* Add Rake task for generate VAPID key

* edit config/initializers/vapid.rb
2017-07-14 12:13:43 +02:00
Albert ARIBAUD
489d162477 fr.json: replace "silencer" with "masquer" (#4196)
"Silencer" as a verb does not exist in French. A good and valid replacement is "masquer".
2017-07-14 12:12:16 +02:00
Yamagishi Kazutoshi
9008ab3407 Do not load unnecessary script files (#4193) 2017-07-14 11:08:56 +02:00
Yamagishi Kazutoshi
87b96f8d33 Add Japanese translations for #3243 (#4192) 2017-07-14 11:03:01 +02:00
masarakki
a49be27145 add validation to tag name (#4194) 2017-07-14 11:02:49 +02:00
Eugen Rochko
27b2355738 Fix #3904 - Adjustable time period for mastodon:media:remove_remote via NUM_DAYS (#4191) 2017-07-14 03:51:17 +02:00
unarist
eeb5923e89 Add object-fit polyfill for Edge (#4182) 2017-07-14 01:59:34 +02:00
Sorin Davidoi
a9067167bb Improve swiping (#4188)
* feat(components/columns_area): Toggle animation settings

* fix(components/media_modal): Center non-visible views

* fix(components/media_modal): Check for null

* refactor(columns_area): Better logic
2017-07-14 00:49:01 +02:00
Sorin Davidoi
a9a0c854e1 fix(components/media_modal): Style issues (#4187) 2017-07-13 22:18:18 +02:00
Sorin Davidoi
0c7c188c45 Web Push Notifications (#3243)
* feat: Register push subscription

* feat: Notify when mentioned

* feat: Boost, favourite, reply, follow, follow request

* feat: Notification interaction

* feat: Handle change of public key

* feat: Unsubscribe if things go wrong

* feat: Do not send normal notifications if push is enabled

* feat: Focus client if open

* refactor: Move push logic to WebPushSubscription

* feat: Better title and body

* feat: Localize messages

* chore: Fix lint errors

* feat: Settings

* refactor: Lazy load

* fix: Check if push settings exist

* feat: Device-based preferences

* refactor: Simplify logic

* refactor: Pull request feedback

* refactor: Pull request feedback

* refactor: Create /api/web/push_subscriptions endpoint

* feat: Spec PushSubscriptionController

* refactor: WebPushSubscription => Web::PushSubscription

* feat: Spec Web::PushSubscription

* feat: Display first media attachment

* feat: Support direction

* fix: Stuff broken while rebasing

* refactor: Integration with session activations

* refactor: Cleanup

* refactor: Simplify implementation

* feat: Set VAPID keys via environment

* chore: Comments

* fix: Crash when no alerts

* fix: Set VAPID keys in testing environment

* fix: Follow link

* feat: Notification actions

* fix: Delete previous subscription

* chore: Temporary logs

* refactor: Move migration to a later date

* fix: Fetch the correct session activation and misc bugs

* refactor: Move migration to a later date

* fix: Remove follow request (no notifications)

* feat: Send administrator contact to push service

* feat: Set time-to-live

* fix: Do not show sensitive images

* fix: Reducer crash in error handling

* feat: Add badge

* chore: Fix lint error

* fix: Checkbox label overlap

* fix: Check for payload support

* fix: Rename action "type" (crash in latest Chrome)

* feat: Action to expand notification

* fix: Lint errors

* fix: Unescape notification body

* fix: Do not allow boosting if the status is hidden

* feat: Add VAPID keys to the production sample environment

* fix: Strip HTML tags from status

* refactor: Better error messages

* refactor: Handle browser not implementing the VAPID protocol (Samsung Internet)

* fix: Error when target_status is nil

* fix: Handle lack of image

* fix: Delete reference to invalid subscriptions

* feat: Better error handling

* fix: Unescape HTML characters after tags are striped

* refactor: Simpify code

* fix: Modify to work with #4091

* Sort strings alphabetically

* i18n: Updated Polish translation

it annoys me that it's not fully localized :P

* refactor: Use current_session in PushSubscriptionController

* fix: Rebase mistake

* fix: Set cacheName to mastodon

* refactor: Pull request feedback

* refactor: Remove logging statements

* chore(yarn): Fix conflicts with master

* chore(yarn): Copy latest from master

* chore(yarn): Readd offline-plugin

* refactor: Use save! and update!

* refactor: Send notifications async

* fix: Allow retry when push fails

* fix: Save track for failed pushes

* fix: Minify sw.js

* fix: Remove account_id from fabricator
2017-07-13 22:15:32 +02:00
unarist
c2753fdfb4 Make tag search case insensitive again (#4184) 2017-07-13 19:31:33 +02:00
unarist
c29c20ab3c Add background color for spoiler input, like toot textarea (#4181) 2017-07-13 14:49:57 +02:00
Eugen Rochko
880a5eb25c Fix boolean columns sometimes having a null value (#4162)
* Fix boolean columns sometimes having a null value

* Fix wrong value being set instead of null
2017-07-13 03:12:25 +02:00
Eugen Rochko
e48d3bfd01 Fix #1010 - When spoiler text is set, enforce sensitivity too (#4176) 2017-07-13 01:47:23 +02:00
unarist
5abb3d8150 Rerender modal on property changes (#4175)
Render function for BundleContainer must not be methods.
React doesn't know dependency of the method, so they won't rerender on property updates.

In this case, when you close modal and open another modal immediately,
old modal will be open instead of new one.
2017-07-12 20:51:44 +02:00
Yamagishi Kazutoshi
c45a75ad34 Update dependencies for Node.js (2017-07-12) (#4167)
* Update @storybook/addon-actions to version 3.1.8

* Update @storybook/react to version 3.1.8

* Update autoprefixer to version 7.1.2

* Update babel-loader to version 7.1.1

* Update babel-preset-env to version 1.6.0

* Update chai to version 4.1.0

* Update js-yaml to version 3.9.0

* Update jsdom to version 11.1.0

* Update postcss-smart-import to version 0.7.5

* Update sinon to version 2.3.7

* Update substring-trie to version 1.0.1

* Update webpack to version 3.2.0

* Update webpack-manifest-plugin to version 1.1.2

* yarn upgrade

* Upgrade extract-text-webpack-plugin to version 3.0.0

* Upgrade intl-relativeformat to version 2.0.0
2017-07-12 15:55:17 +02:00
m4sk1n
3567ac3d3e i18n: @e19eefe, @056b5ed + consistency improvement (pl) (#4171)
* i18n: @e19eefe (pl)

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>

* i18n: @056b5ed (pl)

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>

* i18n: Improve consistency (pl)

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-12 15:53:50 +02:00
Yamagishi Kazutoshi
43f868de3d Add Japanese translations for #4163 and #4129 (#4166)
* Add Japanese translations for #4163

* Add Japanese translations for #4129

* top page -> front page
2017-07-12 14:50:07 +02:00
Yamagishi Kazutoshi
f41590912d Fix broken terms for Japanese (#4170) 2017-07-12 14:49:17 +02:00
Eugen Rochko
056b5ed72f Improve UI of admin site settings (#4163) 2017-07-12 03:24:04 +02:00
Eugen Rochko
1764c32b9e Fix #4067 - Do not make HTTP round-trip when resolving local URL (#4160) 2017-07-12 00:39:15 +02:00
Naoki Kosaka
b21ab498f8 Fix media modal prev button behavior. (#4158) 2017-07-11 19:56:45 +02:00
nightpool
1c6c6b271c Revert "Wrap methods of ProcessFeedService::ProcessEntry in classes (#4151)" (#4157)
This reverts commit 425acecfdb.
2017-07-11 18:19:16 +02:00
Eugen Rochko
e6c81a635b Fix #2848 - Rake task to redownload avatars/headers (#4156)
Can be filtered by a specific domain
Resolves #2292
2017-07-11 17:25:49 +02:00
Eugen Rochko
f93de3a516 Fix #3462 - Require authentication for search API (#4155)
This makes it consistent with /api/v1/accounts/search and
previous behaviour has been an oversight.
2017-07-11 17:08:26 +02:00
Eugen Rochko
e19eefe219 Redesign the landing page, mount public timeline on it (#4122)
* Redesign the landing page, mount public timeline on it

* Adjust the standalone mounted component to the lacking of router

* Adjust auth layout pages to new design

* Fix tests

* Standalone public timeline polling every 5 seconds

* Remove now obsolete translations

* Add responsive design for new landing page

* Address reviews

* Add floating clouds behind frontpage form

* Use access token from public page when available

* Fix mentions and hashtags links, cursor on status content in standalone mode

* Add footer link to source code

* Fix errors on pages that don't embed the component, use classnames

* Fix tests

* Change anonymous autoPlayGif default to false

* When gif autoplay is disabled, hover to play

* Add option to hide the timeline preview

* Slightly improve alt layout

* Add elephant friend to new frontpage

* Display "back to mastodon" in place of "login" when logged in on frontpage

* Change polling time to 3s
2017-07-11 15:27:59 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
8784bd79d0 Require stylesheets in common.js (#4152)
Require stylesheets in common.js because stylesheets are shared by the
entry points.
2017-07-11 15:15:42 +02:00
Yamagishi Kazutoshi
31366334cb Drawer tab according to column (#4135)
* Add notifications link to drawer

* Remove local and public timeline tab in drawer

* Add home
2017-07-11 14:36:27 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
425acecfdb Wrap methods of ProcessFeedService::ProcessEntry in classes (#4151)
ProcessFeedService::ProcessEntry had many methods, so wrap them in classes
representing activities.
2017-07-11 13:37:05 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
29f314a502 Remove redundant inclusion (#4150) 2017-07-11 11:55:48 +02:00
Sorin Davidoi
cc68d1945b refactor: Rewrite immutablejs import statements using destructuring (#4147) 2017-07-11 01:00:14 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
7bacdd718a Fix PrecomputeFeedService for filtered statuses (#4148) 2017-07-11 01:00:01 +02:00
m4sk1n
958fe0f7db i18n: @7a889a8 (pl) (#4144)
* i18n: @7a889a8 (pl)

* Update pl.yml
2017-07-10 19:42:37 +02:00
unarist
e670fa2af6 Update es5-ext to avoid CSP violation (#4145)
Since es5-ext used `new Function("...")`, it caused CSP violation unless "unsafe-eval" included. So this patch updates it to the version which fixes it.

Note that this package is used in polyfills, so loaded only if needed. I've encountered this issue on iOS9.

cf. medikoo/es5-ext@d3864493
2017-07-10 19:41:55 +02:00
Eugen Rochko
a3d93e8bbe Fix #4059 - Remove ModuleConcatenationPlugin (#4139)
It increased memory usage of Webpack 1.5x fold with little benefits
2017-07-10 18:46:46 +02:00
STJrInuyasha
7a889a8e12 Remote following success page (#4129)
* Added a success page to remote following
Includes follow-through links to web (the old redirect target) and back to the remote user's profile

* Use Account.new in spec instead of a fake with only id
(fixes spec)

* Fabricate(:account) over Account.new

* Remove self from the success text
(and all HTML with it)
2017-07-10 18:05:06 +02:00
m4sk1n
d081d4a422 i18n: @2b9721d (pl) (#4143) 2017-07-10 18:04:43 +02:00
Eugen Rochko
34ccc058fa Limit total subscribe retries to 10, but space them out more (#4142)
Since there is little point in retrying so often when a service is down
or does not exist anymore. Subscriptions are renewed 1 day before they
should expire, so retrying in 30 minutes, then 2 hours, then 12 hours
is fine. If even after that, the remote server does not work, there is
little sense in retrying more often than once a day

Also, uniqueness of the job should ensure that failed retries will
not result in multiple retries for the same endpoint when the next
resubscription cycle comes
2017-07-10 18:04:23 +02:00
m4sk1n
7f9a353b94 i18n: @63baab0 (pl) (#4141) 2017-07-10 18:04:06 +02:00
Yamagishi Kazutoshi
31490e0d6c Add Japanese translations (#4140)
* Add Japanese translations for #3879

* Add Japanese translations for #4033

* Add Japanese translations for #4136
2017-07-10 16:32:17 +02:00
のら
ca45bd0361 Add Japanese translation of terms and flash (#4137) 2017-07-10 14:04:05 +02:00
Yamagishi Kazutoshi
63baab088d Fix regular expression for RFC 5646 (regression from #3604) (#4133) 2017-07-10 14:02:18 +02:00
Yamagishi Kazutoshi
2b9721d1b3 Add setting a always mark media as sensitive (#4136) 2017-07-10 14:00:32 +02:00
abcang
617208053c Rescue exceptions related to Goldfinger at FetchRemoteStatusService (#4138) 2017-07-10 13:59:29 +02:00
Sadiq Saif
4aa6cd66fc Change default for auto_play_fit to false for a11y (#4132)
This is per issue #3876
2017-07-10 04:49:48 +02:00
Lynx Kotoura
1c6cbdd4e4 Fix duplication of tag in columns_area.js (#4131)
Deleted ">" just a typo.
2017-07-10 04:37:10 +02:00
Yamagishi Kazutoshi
f8212da329 Add attribute for default privacy to verify credentials (#4075)
* Add attribute for default privacy to verify credentials

* add raw_note

* source
2017-07-10 03:29:34 +02:00
Sorin Davidoi
4122a837fa fix(components/media_modal): Aspect ratio (#4128)
* fix(components/media_modal): Aspect ratio

* fix: Remove useless style
2017-07-09 18:49:07 +02:00
Nolan Lawson
5fa2dd6e65 Use babel-plugin-transform-react-inline-elements (#4109) 2017-07-09 17:34:05 +02:00
abcang
307f3e0dd7 Rescue exceptions related to Goldfinger (#4044)
* Rescue exceptions related to Goldfinger

* Exclude Goldfinger::SSLError
2017-07-09 17:33:21 +02:00
Sorin Davidoi
fc4c74660b Swipeable views (#4105)
* feat: Replace react-swipeable with react-swipeable-views

* fix: iOS 9
2017-07-09 15:02:26 +02:00
unarist
caf938562e Avoid async import if the component is previously loaded (#4127) 2017-07-09 14:52:03 +02:00
unarist
ce3a371eee Fix initial loading of pinned Notifications column (#4126) 2017-07-09 13:04:30 +02:00
m4sk1n
8781a8e203 i18n: minor change (pl) (#4124) 2017-07-09 12:17:00 +02:00
Sorin Davidoi
37c832cdf7 refactor: Make all reducers sync (#4125) 2017-07-09 12:16:08 +02:00
Daniel Hunsaker
f68fa930ea [nanobox] Allow Full-size Uploads (#4123)
The Nginx configurations used by Nanobox previously neglected to increase the default upload size limit. This PR bumps that value up to the current Mastodon limit of 8MiB.
2017-07-09 02:52:36 +02:00
nullkal
007ab330e6 Use charlock_holmes instead of nkf at FetchLinkCardService (#4080)
* Specs for language detection

* Use CharlockHolmes instead of NKF

* Correct mistakes

* Correct style

* Set hint_enc instead of falling back and strip_tags

* Improve specs

* Add dependencies
2017-07-08 22:44:31 +02:00
abcang
794781d121 Change account link to admin account link on report page (#4119) 2017-07-08 18:35:08 +02:00
Sorin Davidoi
91cacb1e8f fix: Rerender Bundle on route change (#4120) 2017-07-08 18:34:55 +02:00
unarist
46f5d3a2e9 Fix first loading of notifications when the column is pinned (#4114) 2017-07-08 17:22:24 +02:00
Yamagishi Kazutoshi
76318f8830 Don't use preview when image size is unknown (#4113) 2017-07-08 17:21:59 +02:00
Yamagishi Kazutoshi
852bda3d32 Use srcSet only when know width (#4112) 2017-07-08 17:20:53 +02:00
Jeroen
0324f807f4 Update and improvement Dutch language strings (#4117)
* Update

* Update
2017-07-08 17:17:02 +02:00
Eugen Rochko
864e3f8d9c Replace OEmbed and initial state Rabl templates with serializers (#4110)
* Replace OEmbed Rabl template with serializer

* Replace initial state rabl with serializer
2017-07-08 14:51:05 +02:00
unarist
102466ac58 Fix JSON serialization of media_attachment (#4111) 2017-07-08 14:50:45 +02:00
Nolan Lawson
63b77f2320 Avoid using getBoundingClientRect to calculate height (#4001) 2017-07-08 01:57:22 +02:00
Sylvhem
8fecd80108 Various fixes in the French translation (#4107)
* Changement de « Changement de mot de passe » en « Sécurité »

* Suppression de « (Two-factor auth) »

Change la valeur de la chaîne « two_factor_authentication » de « Identification à deux facteurs (Two-factor auth) » à « Identification à deux facteurs ».
La traduction anglaise entre parathentèse était redondante et gênait la lecture.

Change the value of the "two_factor_authentication" from "Identification à deux facteurs (Two-factor auth)" to "Identification à deux facteurs".
The English translation in brackets was superflous and was getting in the way of the reader.

* Remplace « ' » par « ’ »

Retire de la traduction les apostrophes droites « ' » (U+0027) au profit des apostrophes typographiques « ’ » (U+2019).
En typographie française, les apostrophes typographiques sont utilisées à la place des apostrophes droites. La traduction était jusqu’ici incohérente et utilisait les deux.

Remove from the translation all the vertical apostrophes (U+0027) in favor of the curly ones (U+2019).
In French typography, typographic apostrophes are used instead of vertical ones. The translation was incoherent and used both.

* Remplace « ... » par « … »

Remplace les séries de trois points par le caractère dédié « … » (U+2026).

Replace all the series of three dots by the dedicated character "…" (U+2026).

* Mise à jour

Crée config/locales/activerecord.fr.yml, ajoute de nouvelles chaînes et met à jour certains textes.
Les compteurs de caractères pour le pseudonyme et la biographie devrait maintenant pouvoir fonctionner même quand l’interface est en français.

Create config/locales/activerecord.fr.yml, add new strings et update some textes.
The caracters counters for the username and the biography should now work even when the interface is in French.

* Remplace « A » par « À »

Remplace « A » par « À » aux endroits où le mot est mal orthographié.

Replace "A" by "À" when the wrong word is used.

* Ajout d’espaces insécables

Ajoute des espaces insécables suivant les régles nécessaires en typographie française.

Add non-breaking spaces following rules of French typography.

* Remplace « certain » par « certain·e »

Harmonise la traduction en remplaçant « certain » par sa forme épicène.

Harmonize the translation by replacing "certain" (sure) by its epicene form.

* Corrige un angliscisme

Remplace « adresse e-mail » par « adresse électronique ».

Replace "adresse e-mail" (e-mail address) by "adresse électronique" (electronic address).
2017-07-08 01:27:22 +02:00
Sorin Davidoi
348d6f5e75 Lazy load components (#3879)
* feat: Lazy-load routes

* feat: Lazy-load modals

* feat: Lazy-load columns

* refactor: Simplify Bundle API

* feat: Optimize bundles

* feat: Prevent flashing the waiting state

* feat: Preload commonly used bundles

* feat: Lazy load Compose reducers

* feat: Lazy load Notifications reducer

* refactor: Move all dynamic imports into one file

* fix: Minor bugs

* fix: Manually hydrate the lazy-loaded reducers

* refactor: Move all dynamic imports to async-components

* fix: Loading modal style

* refactor: Avoid converting the raw state for each lazy hydration

* refactor: Remove unused component

* refactor: Maintain modal name

* fix: Add as=script to preload link

* chore: Fix lint error

* fix(components/bundle): Check if timestamp is set when computing elapsed

* fix: Load compose reducers for the onboarding modal
2017-07-08 00:06:02 +02:00
Eugen Rochko
00df69bc89 Fix #4058 - Use a long-lived cookie to keep track of user-level sessions (#4091)
* Fix #4058 - Use a long-lived cookie to keep track of user-level sessions

* Fix tests, smooth migrate from previous session-based identifier
2017-07-07 23:25:15 +02:00
m4sk1n
7a549f830e i18n: improve consistency (pl) (#4104)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-07-07 20:01:17 +02:00
Nolan Lawson
3f82d8b979 Gracefully stop streaming server (#4103) 2017-07-07 20:01:00 +02:00
m4sk1n
9fe6cfca48 i18n: @18d3fa9 (pl) (#4101) 2017-07-07 17:35:47 +02:00
Eugen Rochko
ebd2dde688 Restore streaming API output format (#4100)
* Restore streaming API output format

Regression from #4090

* Remove whitespace
2017-07-07 16:56:52 +02:00
Eugen Rochko
6e1261f277 Fix notifications including wrong status in JSON (#4097) 2017-07-07 16:19:28 +02:00
Yamagishi Kazutoshi
91d548f7e6 Update webpack-dev-server to v2.5.1 (#4094) 2017-07-07 14:12:45 +02:00
Yamagishi Kazutoshi
76eda2fc21 Add recursive object support to API response (#4095) 2017-07-07 14:12:16 +02:00
Eugen Rochko
1c1819a78a Fix feed author not being enforced in ProcessFeedService (#4092)
Ensure the only allowed author of top-level entries in feed is the person
the feed belongs to (a verified user). Ensure delete events only apply
if the deleted item belonged to that user.
2017-07-07 04:31:40 +02:00
Eugen Rochko
8b2cad5637 Refactor JSON templates to be generated with ActiveModelSerializers instead of Rabl (#4090) 2017-07-07 04:02:06 +02:00
のら
2d6128672f Togglable filter links (#4021)
* Togglable filter links

* Rename is_selected to selected?
2017-07-07 00:48:09 +02:00
Daniel Hunsaker
185b41beb4 [nanobox] Add Automated Backups (#4023)
This PR adds automatic backups to Nanobox instances. The database, Redis, and user files are backed up every day at 03:00 (server time) to the data warehouse component which comes with every Nanobox app. Old backups are automatically cleared out, but the number of backups that are left untouched can be configured by setting the `BACKUP_COUNT` environment variable to any integer value greater than 0 (the default is 1).

Also updated `.env.nanobox` to reflect the current `.env.production.sample`.
2017-07-07 00:46:45 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
2083000027 Set default From address in config (#3756)
The old implementation sets default From address in mailers. It sets
the address from SMTP_FROM_ADDRESS, or notifications@localhost. The
behavior is occasionally undesired results.

In production environment, notifications@localhost is likely to be
incorrect.
In testing environment, the email address should not be varied by a
environment variable.

After appling this change,

In production environment, it will throw an exception when launching
Mastodon.
In testing environment, the address will be fixed with
notifications@localhost.
2017-07-07 00:12:12 +02:00
Damien Erambert
18d3fa953b Add a setting allowing the use of system's default font in Web UI (#4033)
* add a system_font_ui setting on the server

* Plug the system_font_ui on the front-end

* add EN/FR locales for the new setting

* put Roboto after all other fonts

* remove trailing whitespace so CodeClimate is happy

* fix user_spec.rb

* correctly write user_spect this time

* slightly better way of adding the classes

* add comments to the system-font stack for clarification

* use .system-font for the class instead

* don't use multiple lines for comments

* remove trailing whitespace

* use the classnames module for consistency

* use `mastodon-font-sans-serif` instead of Roboto directly
2017-07-06 22:39:56 +02:00
abcang
f76e71825d Improve Activity stream spoiler (#4088) 2017-07-06 21:31:03 +02:00
STJrInuyasha
6bf6d35637 Parse links in status content on update as well as mount (#4042)
* Update links in status content on update as well as mount
Fixes occasional bugs with mentions and hashtags not being set to open in a new column like they should, and instead opening in a new page

* use classList instead of raw className
2017-07-06 21:30:37 +02:00
unarist
9c03fd9cae Unobserve status on unmount (#4013)
This fixes a warning on status unmounting (e.g. deletion).

This also resets IntersectionObserverWrapper on disconnect to avoid `unobserve()` calls
which has bug in Edge.
2017-07-06 21:26:21 +02:00
Mantas
34c8a46d7d Remove ugly blue highlight on Android browsers (#4031) 2017-07-06 21:26:07 +02:00
Quent-in
26949607d2 l10n Occitan locale (#4089)
* Small adjustments

About the report part.

* Update time format
2017-07-06 21:10:12 +02:00
Shin Kojima
e7c0d87d98 Fix embedded SVG fill attribute (#4086)
* Fix embedded SVG fill attribute

SCSS darken/lighten functions may not return a color value, but a color
name like "white".  See following example:

https://www.sassmeister.com/gist/c41da93b87d536890ddf30a1f42e7816

This patch will normalize $color argument to FFFFFF style.

I also changed the function name from "url-friendly-colour" to
"hex-color", Because...

1. The name "url-friendly" is not meaningful enough to describe what it
   does.

2. It is familier to me using "color" rather than "colour"

    kojima:kojiMac mastodon[master]$ git grep -l colour
    app/javascript/styles/boost.scss
    spec/fixtures/files/attachment.jpg

    kojima:kojiMac mastodon[master]$ git grep -l color
    .rspec
    .scss-lint.yml
    Gemfile.lock
    app/javascript/mastodon/features/status/components/action_bar.js
    app/javascript/styles/about.scss
    app/javascript/styles/accounts.scss
    app/javascript/styles/admin.scss
    app/javascript/styles/basics.scss
    app/javascript/styles/boost.scss
    app/javascript/styles/compact_header.scss
    app/javascript/styles/components.scss
    app/javascript/styles/containers.scss
    app/javascript/styles/footer.scss
    app/javascript/styles/forms.scss
    app/javascript/styles/landing_strip.scss
    app/javascript/styles/reset.scss
    app/javascript/styles/stream_entries.scss
    app/javascript/styles/tables.scss
    app/javascript/styles/variables.scss
    app/views/admin/subscriptions/_subscription.html.haml
    app/views/layouts/application.html.haml
    app/views/layouts/error.html.haml
    app/views/manifests/show.json.rabl
    bin/webpack-dev-server
    config/initializers/httplog.rb
    public/500.html
    public/emoji/1f1e6-1f1e8.svg
    public/emoji/1f1ec-1f1f8.svg
    public/emoji/1f1f3-1f1ee.svg
    public/emoji/1f1fb-1f1ec.svg
    spec/fixtures/requests/idn.txt
    yarn.lock

* Add semicolon
2017-07-06 15:27:02 +02:00
m4sk1n
6d106d3943 i18n: minor changes in Polish translation (#4087)
* i18n: minor changes in Polish translation

* Update pl.json
2017-07-06 15:25:27 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
a37cf9548c Explicitly require MIME::Types (#4083) 2017-07-05 23:58:03 +02:00
abcang
5e6acf9601 Fix Nokogiri::HTML at FetchLinkCardService (#4072) 2017-07-05 14:54:21 +02:00
unarist
b52a5e6bd6 Show LoadMore button on Notifications even if all items are filtered (#4077) 2017-07-05 14:51:53 +02:00
Yamagishi Kazutoshi
bb194ddb3c Format datetime of subscriptions on admin UI (#4078) 2017-07-05 14:51:28 +02:00
m4sk1n
a38b34c37a i18n: Updated Polish translation (#4068)
* i18n: Updated Polish translation

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>

* fuggin nano
2017-07-04 23:34:00 +02:00
Gyuhwan Park
1921ab40ea i18n: Update korean translation (#4066)
* Added Korean Translation (based on japanese)

* Update korean translation

* Update korean translation: fix syntax error

* Updated korean translation

* Update korean translation

* Update ko.json

Translate non-translated parts

* Update ko.yml

Translated missed parts - and fixed some typos

* Create simple_form.ko.yml

* Updated korean translation

* i18n: fix test fails

* Updated korean translation
2017-07-04 17:09:17 +02:00
Minori Hiraoka
976c18aa5f Fix Korean translation (#4065)
* Added Korean Translation (based on japanese)

* Update korean translation

* Update korean translation: fix syntax error

* Updated korean translation

* Update korean translation

* Update ko.json

Translate non-translated parts

* Update ko.yml

Translated missed parts - and fixed some typos

* Create simple_form.ko.yml

* Update simple_form.ko.yml

Translation error fix - password change form

* Update simple_form.ko.yml

* Update ko.json

Missing translation
2017-07-04 16:48:22 +02:00
Gyuhwan Park
4cddef1cea i18n: Add korean translation (#4064)
* Added Korean Translation (based on japanese)

* Update korean translation

* Update korean translation: fix syntax error

* Updated korean translation

* Update korean translation

* Update ko.json

Translate non-translated parts

* Update ko.yml

Translated missed parts - and fixed some typos

* Create simple_form.ko.yml

* Updated korean translation

* i18n: fix test fails
2017-07-04 16:11:23 +02:00
Yamagishi Kazutoshi
cbe94b88e2 Change webpack-dev-server repository (#4061) 2017-07-04 15:19:54 +02:00
Yamagishi Kazutoshi
275c5b51ed Customizable privacy policy from admin interface (#4062) 2017-07-04 15:19:24 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
f85dbe83c8 Remove sort in Feed (#4050)
In from_redis method, statuses retrieved from the database was mapped to
the IDs retrieved from Redis. It was equivalent to order from high to low
because those IDs are sorted in the same order.
Statuses are ordered with the ID by default, so we do not have to reorder.
Sorting statuses in the database is even faster since the IDs are indexed
with B-tree.
2017-07-03 13:17:27 +02:00
Yamagishi Kazutoshi
a9c326b200 Upgrade chai-enzyme, precss and uws (#4010)
* Update chai-enzyme to v0.8.0

* Upgrade precss to v2.0.0

* Upgrade uws to v8.14.0
2017-07-03 11:56:58 +02:00
Yamagishi Kazutoshi
92f1c474f3 Add fa-fw class to user agent icon (#4047) 2017-07-03 11:04:35 +02:00
abcang
a6d02cff36 Rescue exceptions caused by FetchLinkCardService (#4045) 2017-07-03 11:03:34 +02:00
のら
be94f9e35d Update Japanese translation (#4051) 2017-07-03 11:02:59 +02:00
Nolan Lawson
e282580101 Faster emojify() by avoiding str.replace() entirely (#4049) 2017-07-03 11:02:36 +02:00
Ratmir Karabut
331f0953e9 Update Russian translation (sessions) (#4041)
* Add Russian translation (ru)

* Fix a missing comma

* Fix the wording for better consistency

* Update Russian translation

* Arrange Russian setting alphabetically

* Fix syntax error

* Update Russian translation

* Fix formatting error

* Update Russian translation

* Update Russian translation

* Update ru.jsx

* Fix syntax error

* Remove two_factor_auth.warning (appears obsolete)

* Add missing strings in ru.yml

A lot of new strings translated, especially for the newly added admin section

* Fix translation consistency

* Update Russian translation

* Update Russian translation (pluralizations)

* Update Russian translation

* Update Russian translation

* Update Russian translation (pin)

* Update Russian translation (account deletion)

* Fix extra line

* Update Russian translation (sessions)
2017-07-03 01:30:22 +02:00
Damien Erambert
133b892e0d Update French locales (#4034)
* add missing locales for French translation

* accent "Media" in the front-end locales

* images => médias

* Change 'rapport' to 'signalement' in French locales to be more coherent

* fix typo

* remove duplicate EN locale

* translate missing locales

* update missing locale

* fix typo

* unify with "utilisateur⋅ice⋅s"

* address PR comments
2017-07-02 18:36:35 +02:00
Sorin Davidoi
60da49f856 fix(components/columns_area): Increase delta for swipe detection (#4037) 2017-07-02 15:55:50 +02:00
unarist
d1d94216d1 Update Japanese translation (Credentials -> Security) (#4025) 2017-07-01 21:18:38 +02:00
Eugen Rochko
bf50e3e5ae Fix height issue in report modal 2017-07-01 14:50:10 +02:00
Nolan Lawson
a978b88997 Faster emojify() algorithm, avoid regex replace (#4019)
* Faster emojify() algorithm, avoid regex replace

* add semicolon
2017-06-30 17:29:22 +02:00
Matt Jankowski
6dd5eac7fc Add controller spec for manifests controller (#4003) 2017-06-30 13:43:34 +02:00
Nolan Lawson
968354923e Fix webpack-dev-server on Windows (#4000)
* Fix webpack-dev-server on Windows

* Serve webpack from 0.0.0.0, access at 127.0.0.1
2017-06-30 13:43:26 +02:00
Matt Jankowski
59ddf81a45 Version bumps for gems (#4002)
* Update aws-sdk to version 2.10.4

* Update bootsnap to version 1.1.1

* Update capistrano to version 3.8.2

* Update capybara to version 2.14.4

* Update cld3 to version 3.1.3

* Update http_accept_language to version 2.1.1

* Update sidekiq to version 5.0.3

* Update rspec-sidekiq to version 3.0.3

* Update sidekiq-scheduler to version 2.1.7

* Update oj to version 3.2.0

* Update openssl to version 2.0.4

* Update pg to version 0.21.0

* Update twitter-text to version 1.14.6

* Update unicode-display_width to version 1.3.0

* Update scss_lint to version 0.54.0

* Update hamlit to version 2.8.4

* Update erubi to version 1.6.1

* Update httplog to version 0.99.4

* Update aws-sdk to version 2.10.6
2017-06-30 13:42:04 +02:00
Yamagishi Kazutoshi
3a7106f05a Fix that AdminMailer does not send (#4012) 2017-06-30 13:40:43 +02:00
Yamagishi Kazutoshi
5c7a4f0b32 Remove babel-cli (#4011) 2017-06-30 13:40:14 +02:00
Yamagishi Kazutoshi
0e09048537 Fix broken style in media gallery (regression from #3963) (#4014) 2017-06-30 13:40:00 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
7362469d89 Do not raise an error if PrecomputeFeed could not find any status (#4015) 2017-06-30 13:39:42 +02:00
abcang
1273fbf86e Rescue Addressable::URI::InvalidURIError at Remotable (#4017) 2017-06-30 13:38:36 +02:00
Yamagishi Kazutoshi
a27879c0cf Replace state to /web when root path (#4009) 2017-06-30 05:37:41 +02:00
Naoki Kosaka
049cea30b0 Fix media-gallery, overflow is hidden. (#4008) 2017-06-30 05:37:17 +02:00
abcang
b342c81c17 rescue HTTP::ConnectionError (#3992) 2017-06-29 13:04:07 +02:00
Yamagishi Kazutoshi
ead14f5bf0 Upgrade jsdom to version 11.0.0 (#3994) 2017-06-29 13:03:03 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
0a53ca444a Cover Admin::AccountsController more (#3327) 2017-06-29 01:43:10 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
f79c10162e Use multiple pairs for zadd in PrecomputeFeedService (#3990) 2017-06-29 01:25:31 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
60b2b56d38 Reduce number of commands in FeedManager#trim (#3989) 2017-06-29 01:17:26 +02:00
Eugen Rochko
b6a19e7b89 Bump version to 1.4.7 2017-06-28 17:44:17 +02:00
Eugen Rochko
71bc75e6ac Do not fail to create access token if superapp was never created (#3986) 2017-06-28 17:43:48 +02:00
Yamagishi Kazutoshi
e4fee6c138 Add Japanese translations (#3985)
ref #3929, #3935, #3949, #3981
2017-06-28 16:45:21 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
7d8e3721ae Overwrite old statuses with reblogs in PrecomputeFeedService (#3984) 2017-06-28 14:50:23 +02:00
m4sk1n
fb421a1f46 i18n: added email to activerecord.pl.yml (#3981) 2017-06-28 14:07:53 +02:00
m4sk1n
2a9805b987 i18n: Minor fix in devise.pl.yml (#3978) 2017-06-27 23:14:02 +02:00
m4sk1n
126f929c39 i18n: Use instance name in email notifications instead of Mastodon (pl) (#3976)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-06-27 23:10:43 +02:00
m4sk1n
da42bfadb5 i18n: E-mail notifications to admins about new reports (pl) (#3975) 2017-06-27 22:21:35 +02:00
m4sk1n
6ad72728f6 i18n: Turn report screen into a modal (pl) (#3974) 2017-06-27 22:14:31 +02:00
Sorin Davidoi
64d9c016bd fix(components/status): Up & down jump due to content being added to the DOM (#3972) 2017-06-27 18:43:53 +02:00
Eugen Rochko
12e7c81dd8 Turn report screen into a modal (#3965) 2017-06-27 18:07:21 +02:00
Midgard
16d0aed403 Use instance name in email notifications instead of "Mastodon" (#3763)
* Use instance name in "password changed" mail

instead of "Mastodon".

Fixes tootsuite#2620.

* Use instance name in password reset mail

instead of "Mastodon".
2017-06-27 14:22:36 +02:00
Debanshu Kundu
da9317fa56 #1456 Added rake task to add a user. (#1482) 2017-06-27 14:18:53 +02:00
Sorin Davidoi
be92babd00 Responsive images in media gallery (#3963)
* feat(components/media_gallery): Responsive images

* fix(components/media_gallery): Link to image URL
2017-06-27 13:46:37 +02:00
Yamagishi Kazutoshi
e2dd576a1b Update dependencies for Node.js (#3967)
* Update @storybook/addon-actions to v3.1.6

* Update @storybook/react to v3.1.6

* Update babel-loader to v7.1.0

* Update babel-plugin-transform-react-remove-prop-types to v0.4.6

* Update enzyme to v2.9.1

* Update fsevents to v1.1.2

* Update intersection-observer to v0.3.2

* Update npmlog to v4.1.2

* Update pg to v6.4.0

* Update postcss-loader to v2.0.6

* Update rails-ujs to v5.1.2

* Update react to v15.6.1

* Update react-addons-shallow-compare to v15.6.0

* Update react-dom to v15.6.0

* Update react-notification to v6.7.1

* Update react-test-renderer to v15.6.1

* Update react-textarea-autosize to v5.0.7

* Update redux to v3.7.1

* Update resolve-url-loader to v2.1.0

* Update sass-loader to v6.0.6

* Update sinon to v2.3.5

* Update stringz to v0.2.2

* Update uuid to v3.1.0

* Update websocket.js to v0.1.12

* Update yargs to v8.0.2

* yarn upgrade
2017-06-27 13:46:11 +02:00
Yamagishi Kazutoshi
8f2c91568c Maintain aspect ratio for preview image (#3966) 2017-06-27 13:43:53 +02:00
Yamagishi Kazutoshi
98eaa2aa27 Update Rails to v5.1.2 (#3968) 2017-06-27 13:41:03 +02:00
Eugen Rochko
42b8220632 Fix #1624 - Send e-mail notifications to admins about new reports (#3949) 2017-06-27 00:04:00 +02:00
ThibG
a91d968cab Raise an error if salmon request response is unsatisfactory (#3960) 2017-06-26 19:39:58 +02:00
m4sk1n
646de92781 i18n: Updated Polish translation (#3956)
* i18n: Updated Polish translation

* Update pl.yml
2017-06-26 17:18:45 +02:00
m4sk1n
ae2b722f55 i18n: Warning to look into the spam folder (pl) (#3955) 2017-06-26 17:10:54 +02:00
Daniel Hunsaker
7aeb9168b0 Add .gitattributes file to avoid unwanted CRLF (#3954)
When Windows checks out files, it defaults to changing line endings to CRLF. If these files are then copied to a Linux system to be run, and the endings aren't changed at some point in that process, things break. This file forces git to use LF for all text files on all systems (except the request testing specfiles) to prevent issues everywhere.
2017-06-26 13:15:24 +02:00
Alda Marteau-Hardi
f53ed108b0 Translate pin/unpin and fix some inconsistencies in gender neutral strings (#3952) 2017-06-26 13:04:36 +02:00
Yamagishi Kazutoshi
285038972b Stop using Babel with streaming server (#3950) 2017-06-26 04:49:39 +02:00
Takuya Yoshida
e5563843a2 Re-fix errorMiddleware (#3922) 2017-06-26 01:46:15 +02:00
unarist
c972e1ee1f Ignore DB_NAME for development env on streaming as well as rails side (#3948) 2017-06-26 01:45:50 +02:00
Eugen Rochko
5e8d037e27 Fix #3910 - Require OTP authentication to disable 2FA (#3935)
* Fix #3910 - Require OTP authentication to disable 2FA. Also, remove ability
to generate new OTP backup codes *after* initial backup codes were handed
out during activation

* Restore recovery code re-generation

* Improve display of some 2FA elements
2017-06-25 23:51:46 +02:00
Eugen Rochko
ed7dc1704d Bind web UI access tokens to sessions (#3940)
* Add overview of active sessions

* Better display of browser/platform name

* Improve how browser information is stored and displayed for sessions overview

* Fix test

* Fix #2347 - Bind web UI access token to session

When you logout, session also destroys the access token, so it's no longer
valid. If access token is destroyed some other way, the session is also
destroyed, requiring a re-login.

Fix #1681 - Add scheduler to remove revoked access tokens and grants

* Fix test
2017-06-25 23:51:32 +02:00
amazedkoumei
436ce03772 fix unnecessary variable (#3947) 2017-06-25 23:29:22 +02:00
Eugen Rochko
d821aba002 Rename "Credentials" page to "Security" for clarity (#3941)
* Rename "Credentials" page to "Security" for clarity

* Change "security" icon from cog to lock
2017-06-25 22:13:02 +02:00
Sorin Davidoi
4ce1540094 fix(features/compose): Handle external changes to the textarea (#3632) 2017-06-25 21:43:27 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
67243bda31 Cover Auth::RegistrationsController more (#3353) 2017-06-25 21:42:55 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
8f991831b8 Cover Admin::DomainBlocksController more (#3329)
Also domain_block fabricator now sets unique domains
2017-06-25 21:42:36 +02:00
amazedkoumei
87efa38721 more free pgconfig by .env (#3909)
* more free pgconfig for streaming by .env

* fix wrong default values

* database.yml read ENV as same as streaming server
2017-06-25 18:13:31 +02:00
Eugen Rochko
f7301bd5b9 Add overview of active sessions (#3929)
* Add overview of active sessions

* Better display of browser/platform name

* Improve how browser information is stored and displayed for sessions overview

* Fix test
2017-06-25 16:54:30 +02:00
PFM
099a3b4eac Fix "undefined" in className (#3939) 2017-06-25 16:02:56 +02:00
unarist
3d4e21f1ec Don't set ASSET_HOST on build:development (#3936)
Setting ASSET_HOST to `http://0.0.0.0:8080` makes urls in manifest.json to
be invalid, e.g. `http://0.0.0.0:8080/packs/application.js`.

Anyway, we don't need set this on build:development because assets would
be delivered from same origin in development (and w/o dev-server).
2017-06-25 12:52:42 +02:00
unarist
68dca26a5d Fix react-intl/locale-data import issue on production build (#3937)
Webpack seems to fail to import `react-intl/locale-data/*.js` if those
files has been proceed by babel, and this also breaks applying our translation.

Note that this won't be a problem on English locale, because react-intl
includes it as default and works fine without manually added locale-data.
Also this issue seems to only occurs on production build, but I'm not sure
about reason.
2017-06-25 12:49:53 +02:00
unarist
1fc096ec75 Fix elephant in onboarding modal being very small sized on small devices (#3932) 2017-06-24 23:18:32 +02:00
unarist
21c2bc119c Clean column collapsible (#3931)
* Remove unused column_collapsable.js
* Remove old styles
* Extract `> div`  style to independent class
2017-06-24 23:18:11 +02:00
Sorin Davidoi
d23293c762 feat(components/onboarding_modal): Swipe between pages (#3934) 2017-06-24 23:17:39 +02:00
unarist
138e5a0b1e Fix webpack config for Windows (#3926) 2017-06-24 14:03:52 +02:00
Yamagishi Kazutoshi
79dacea962 Fix #3924 (regression from #3906) (#3925) 2017-06-24 12:24:02 +02:00
unarist
4e6b5e7879 Use debounce for dispatch scrollTopNotification and expandNotifications (#3700) 2017-06-24 02:43:26 +02:00
Daniel Hunsaker
c0979381a4 Fix a typo and give CW'd statuses the right cursor (#3918) 2017-06-23 23:13:27 +02:00
Eugen Rochko
676f577e7e Fix webpack-dev-server until it's fixed upstream (#3916) 2017-06-23 19:40:51 +02:00
Yamagishi Kazutoshi
c1a8e3d1eb Use Class and Property Decorators (#3730)
ref https://tc39.github.io/proposal-decorators/
2017-06-23 19:36:54 +02:00
Takuya Yoshida
0c44316b22 Fix errorMiddleware to prevent "TypeError: res.writeHead is not a function" (#3913)
* Fix errorMiddleware

* Add "eslint-disable-line no-unused-vars"
2017-06-23 19:22:02 +02:00
Sorin Davidoi
2211e8d1cd Revocable sessions (#3616)
* feat: Revocable sessions

* fix: Tests using sign_in

* feat: Configuration entry for the maximum number of session activations
2017-06-23 18:50:53 +02:00
Nolan Lawson
3783cadf2d Apply babel to react-intl to remove prop-types (#3914) 2017-06-23 18:21:33 +02:00
Eugen Rochko
a071047c13 Merge branch 'sorin-davidoi-swipe-gestures' 2017-06-23 17:52:56 +02:00
Eugen Rochko
281f07244b Merge branch 'swipe-gestures' of git://github.com/sorin-davidoi/mastodon into sorin-davidoi-swipe-gestures 2017-06-23 17:52:39 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
6f34a6a77f Add index statuses on account_id and id (#3895) 2017-06-23 17:46:00 +02:00
Nolan Lawson
e078919f07 Upgrade to Webpack 3 with module concatenation (#3912) 2017-06-23 17:44:55 +02:00
Eugen Rochko
7b13e6efc2 Bump version to 1.4.6 2017-06-23 17:02:14 +02:00
Eugen Rochko
3f59238207 Add important test for full-width hashtags (#3911) 2017-06-23 17:01:53 +02:00
Yamagishi Kazutoshi
eff9416469 Remove unused variables (#3906) 2017-06-23 16:05:04 +02:00
Yamagishi Kazutoshi
6fbb3841a6 Add prefix to setting toggle ID (#3907) 2017-06-23 13:55:05 +02:00
Sorin Davidoi
d8c4781377 fix: Apply :hover, :focus and :active only when multiple columns 2017-06-23 13:48:46 +02:00
Sorin Davidoi
bc6e958229 feat: Swipeable media 2017-06-23 13:48:46 +02:00
Sorin Davidoi
a6d8d1036a feat: Swipeable columns 2017-06-23 13:48:46 +02:00
Sorin Davidoi
3d403a013d chore(yarn): Install react-swipeable 2017-06-23 13:40:58 +02:00
Ratmir Karabut
9ca02a00a6 Update Russian translation (#3902)
* Add Russian translation (ru)

* Fix a missing comma

* Fix the wording for better consistency

* Update Russian translation

* Arrange Russian setting alphabetically

* Fix syntax error

* Update Russian translation

* Fix formatting error

* Update Russian translation

* Update Russian translation

* Update ru.jsx

* Fix syntax error

* Remove two_factor_auth.warning (appears obsolete)

* Add missing strings in ru.yml

A lot of new strings translated, especially for the newly added admin section

* Fix translation consistency

* Update Russian translation

* Update Russian translation (pluralizations)

* Update Russian translation

* Update Russian translation

* Update Russian translation (pin)

* Update Russian translation (account deletion)

* Fix extra line
2017-06-22 23:28:58 +02:00
nightpool
3e8e9c8ae4 Use the stable RVM installer (#3901)
as mentioned by ElvenSpellmaker here: https://github.com/rvm/rvm/issues/4068

Adds a workaround for the issue mentioned by @abcang here: https://github.com/tootsuite/mastodon/pull/3897#issuecomment-310436668 and makes sure that we're using the stable installer to install the stable version.
2017-06-22 23:28:52 +02:00
Charlotte Fields
7bc1805827 fixed vagrantfile (#3897) 2017-06-22 18:35:27 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
e27f792c24 Some minor change and spec for Account (#3813)
* Introduce domains method to Account relation

Account had followers_domains method, which was excessively specific.
Let relation of Account have domains method instead.

* Move follow_mapping in Account to AccountInteractions

* Introduce shared examples for AccountAvatar inclusion

* Cover Account more
2017-06-22 18:34:27 +02:00
Quent-in
98fab24bea Update of doorkeeper.oc.yml (#3896)
Just some adjustements
2017-06-22 13:39:13 +02:00
Eugen Rochko
f566c47dda Fix travis builds
https://github.com/travis-ci/travis-ci/issues/7941#issuecomment-310320597
2017-06-22 13:24:00 +02:00
Eugen Rochko
0190aac240 Fix regression from #3842 (#3892)
* Fix regression from #3842

Simplify the query by omitting all direct statuses. Private statuses
are allowed because they are from accounts we are following (so
by definition)

Resolves #3887 (alternative)

* Adjust test
2017-06-22 02:38:50 +02:00
unarist
cc382c5006 Don't attach IntersectionObserver for wrapped statuses (#3883)
(This patch has been merged as bugfix and reverted, but still valuable as
improvement)

Previously, we've attached IntersectionObserver twice for boosted statuses:
wrapper Status and wrapped Status. but wrapped Status don't need to manage
intersection and visibility by itself, because it's a part of wrapper Status.
2017-06-21 06:47:36 +02:00
Eugen Rochko
946a166791 Revert #3851 (#3878) 2017-06-21 01:37:15 +02:00
Eugen Rochko
31cd649041 Revert "Don't attach IntersectionObserver for wrapped statuses" (#3877)
* Revert "Bump version to 1.4.4"

This reverts commit 1585b0c6cc.

* Revert "Fix conversations (fixes #3869) (#3870)"

This reverts commit 15b43f555d.

* Revert "Fix streaming server. Redis connection subscribe for each channel. (#3828)"

This reverts commit d8ec832806.

* Revert "Filter direct statuses in Status.as_home_timeline (#3842)"

This reverts commit bab5a18232.

* Revert "Fix RemoteFollow behavior (#3868)"

This reverts commit a20cf3b64e.

* Revert "Update fabricator for MediaAttachment to attach a file according to type (#3862)"

This reverts commit 356df7ae6b.

* Revert "Upgrade React Router (#3677)"

This reverts commit 8f03fdce7f.

* Revert "Do not call setState from unmounted component (#3853)"

This reverts commit 1fc6cb4997.

* Revert "Replace TextIconButton for SensitiveButton to IconButton (#3759)"

This reverts commit eb832e88f4.

* Revert "Fix RTL detection on Ruby side (#3867)"

This reverts commit b16b69350e.

* Revert "i18n: Fixed typo in Polish translation (#3864)"

This reverts commit da6fa029f6.

* Revert "Don't attach IntersectionObserver for wrapped statuses (#3863)"

This reverts commit 94ad0706f5.
2017-06-21 01:33:14 +02:00
Eugen Rochko
1585b0c6cc Bump version to 1.4.4 2017-06-20 21:32:37 +02:00
ThibG
15b43f555d Fix conversations (fixes #3869) (#3870)
* Actually create conversations given explicit URIs

* Try to get the parent toot in before validation, to avoid creating a new conversation
2017-06-20 20:44:32 +02:00
猫吸血鬼ディフリス / 猫ロキP
d8ec832806 Fix streaming server. Redis connection subscribe for each channel. (#3828) 2017-06-20 20:41:41 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
bab5a18232 Filter direct statuses in Status.as_home_timeline (#3842)
The classes using Status.as_home_timeline, namely Feed and
PrecomputeFeedService are expected to filter direct statuses as
FanOutWriteService does, but their filtering were incomplete or missing.

This commit solves the problem by filtering direct statuses in
as_home_timeline as the other similar methods such as as_public_timeline
does.
2017-06-20 20:41:23 +02:00
unarist
a20cf3b64e Fix RemoteFollow behavior (#3868)
* Invalid acct is an error. not "2 errors".
* Empty input should be different error from invalid acct
2017-06-20 20:40:56 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
356df7ae6b Update fabricator for MediaAttachment to attach a file according to type (#3862)
This fixes a random spec failures since commit
d55f207274.
2017-06-20 20:40:45 +02:00
Sorin Davidoi
8f03fdce7f Upgrade React Router (#3677)
* chore(yarn): Remove react-router

* chore(yarn): Remove react-router-scroll

* chore(yarn): Remove history

* chore(yarn): Add react-router-dom

* chore: Remove usages of react-router-scroll

* refactor: Upgrade to react-router-web

* refactor: Use fork of react-router-scroll

This reverts commit 2ddea9a6c8d39fc64b7d0b587f3fbda7a45a7fa2.

* fix: Issues mentions in the PR feedback
2017-06-20 20:40:03 +02:00
alpaca-tc
1fc6cb4997 Do not call setState from unmounted component (#3853)
Stop an executing task if the component already unmounted.
2017-06-20 20:37:09 +02:00
Yamagishi Kazutoshi
eb832e88f4 Replace TextIconButton for SensitiveButton to IconButton (#3759)
* Replace TextIconButton for SensitiveButton to IconButton

* line-height
2017-06-20 19:43:09 +02:00
unarist
b16b69350e Fix RTL detection on Ruby side (#3867)
This fixes below bugs:

* pipe characters being counted as RTL character
* only first word being checked
2017-06-20 18:45:09 +02:00
m4sk1n
da6fa029f6 i18n: Fixed typo in Polish translation (#3864) 2017-06-20 18:34:27 +02:00
unarist
94ad0706f5 Don't attach IntersectionObserver for wrapped statuses (#3863)
This fixes a bug that sometimes boosted statuses being hidden on scrolling.

Previously, we've attached IntersectionObserver twice for boosted statuses:
wrapper Status and wrapped Status. This will call intersection handler twice,
so this may results race condition...probably.
2017-06-20 04:12:51 +02:00
unarist
bf8c2c4348 Clicking on the CW text should expand the status (#3855) 2017-06-20 01:34:10 +02:00
unarist
aa58cca040 Set cursor:pointer only when necessary (#3857) 2017-06-19 18:27:07 +02:00
のら
5cc7cd8518 Add Japanese translation "Action taken by" (#3850) 2017-06-19 15:12:41 +02:00
masarakki
ff142eb64d setting-for-account-deletable (#3852) 2017-06-19 15:12:31 +02:00
Yamagishi Kazutoshi
500e28442f Re-add disableHostCheck (regression #3729) (#3854)
ref #2790
2017-06-19 14:01:31 +02:00
Daigo 3 Dango
5bd3715a4c Link to /about from public page on a single user instance (#3814)
There was no link for visitors to follow to see the about page.
2017-06-19 11:32:28 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
3d13f6ea0c Cover Block more (#3837) 2017-06-19 11:31:37 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
6eefccdacc Cover DomainBlock more (#3838) 2017-06-19 11:31:27 +02:00
Gô Shoemake
29a22691d2 Fix character/grapheme count stuff (#3839)
* Bring Toot button in line with counter

Both should use stringz I guess

* Use grapheme_length for character count
2017-06-19 11:31:14 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
d55f207274 Cover Export more (#3840) 2017-06-19 11:30:27 +02:00
alpaca-tc
cf6fe4f8cb Unobserve status on unmount (#3851) 2017-06-19 11:29:57 +02:00
spla
4367443287 Added new Catalan strings (#3843)
* Add Catalan language

* Add Catalan language

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update settings_helper.rb

* Update mastodon.js

* Update index.js

* Update application.rb

* Update ca.yml

* removed extra spaces at line 225

* Catalan translation update

added activerecord.ca.yml

* Update activerecord.ca.yml

Done

* Updated activerecord.ca.yml

* Catalan language updated

* Catalan language updated

* Catalan language updated

* Catalan language updated

* Catalan language updated

* Update ca.json

Removed :

<<<<<<< HEAD
  "getting_started.support": "{faq} • {userguide} • {apps}",
=======
>>>>>>> upstream/master
2017-06-19 10:29:18 +02:00
alpaca-tc
8d2b3ada80 Fixes streaming callbacks of HashtagTimeline (#3849) 2017-06-19 10:28:35 +02:00
Eugen Rochko
f3be605286 Rename FollowRemoteAccountService to ResolveRemoteAccountService (#3847)
Rename Activitypub to ActivityPub
2017-06-19 01:51:04 +02:00
Eugen Rochko
aebebdc5d1 Debounce autosuggestions (#3836)
* Debounce autosuggestions

* Remove duplicate import
2017-06-19 01:50:56 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
05e4728de7 Cover Favourite more (#3841) 2017-06-19 01:38:50 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
b51945f096 Spec AccountDomainBlock (#3816) 2017-06-18 02:59:49 +02:00
Nolan Lawson
1f2abd8d67 Fix jittery scrolling for Chromium browsers (#3776) (#3832) 2017-06-18 02:59:29 +02:00
Nolan Lawson
1d9f9352a6 handle resize in a debounce() (#3834) 2017-06-18 02:57:41 +02:00
Yamagishi Kazutoshi
53e42bf91e Upgrade Webpacker to version 2.0 (#3729) 2017-06-18 02:57:09 +02:00
nightpool
94d0e012de Whitelist allowed classes for federated statuses (#3810)
* Whitelist allowed classes for federated statuses

Allowed classes are currently:

 - Any microformats class (h/p/u/dt/e-*)
 - the classes mention, hashtag, ellipses and invisible.

this last one is somewhat suspect, but Mastodon currently uses it to render hidden link text.

resolved #3790

* Fix code style
2017-06-17 20:26:05 +02:00
Quent-in
8fd931dc12 l10n update for account deletion (#3820)
* l10n update for acount deletion

* l10n little change

* l10n little changes

Less passive voice, more natural.

* Update oc.yml

Correction, " added
2017-06-17 20:21:25 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
74d10b9b9d Spec UserMailer (#3757) 2017-06-17 01:15:00 +02:00
unarist
2356580cee Use cross-env for npm run on Windows (#3789) 2017-06-17 01:14:42 +02:00
abcang
1840a352f5 Fix ogp url (#3802) 2017-06-16 22:38:26 +02:00
Yamagishi Kazutoshi
c93d0978f2 Upgrade react-immutable-pure-component to version 1.0.0 (#3786) 2017-06-16 01:46:12 +02:00
Yamagishi Kazutoshi
df4f4e94b3 Add alt attribute to ImageLoader (#3765) 2017-06-15 14:10:41 +02:00
ThibG
51b2f789bd Fix #3633 by not spawning RemoteProfileUpdateWorker from FetchRemoteAccountService (#3642) 2017-06-15 11:04:23 +02:00
Eugen Rochko
947887f261 Bump version to 1.4.3 2017-06-15 03:03:42 +02:00
m4sk1n
6f34fdb616 updated Polish translation (#3751)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-06-15 02:00:23 +02:00
Eugen Rochko
8518d005fd Fix regression from #3490 - filter out hidden statuses from ancestors/descendants even if the viewer is anonymous (#3752) 2017-06-15 02:00:08 +02:00
Eugen Rochko
bb911043de Fix regression from #3748 - properly set defaultColumns (#3750) 2017-06-14 23:07:06 +02:00
unarist
da0333f1cb Add Japanese translation for Account deletion (#3747) 2017-06-14 22:00:08 +02:00
unarist
d8a0ee1956 Fix merge default columns (#3748)
mergeDeep also merges columns, but it should be replaced simply.

So in the new function, first apply mergeDeep except columns, and set default columns if columns unset.
2017-06-14 21:59:52 +02:00
Eugen Rochko
91c71471ab Fix account delete form not accepting password, update suspended (#3745)
account before removing content for quicker feedback to end-users
2017-06-14 20:30:12 +02:00
m4sk1n
98eacb2238 i18n: updated Polish translation (#3744) 2017-06-14 20:08:00 +02:00
Eugen Rochko
80c13bf0ef Save settings when they are changed (#3743) 2017-06-14 18:59:02 +02:00
Eugen Rochko
e17c2e5da5 Batched remove status service (#3735)
* Make Pubsubhubbub::DistributionWorker handle both single stream entry
arguments, as well as arrays of stream entries

* Add BatchedRemoveStatusService, make SuspendAccountService use it

* Improve method names

* Add test

* Add more tests

* Use PuSH payloads of 100 to have a clear mapping of
1000 input statuses -> 10 PuSH payloads

It was nice while it lasted
2017-06-14 18:01:35 +02:00
Eugen Rochko
4a618908e8 Account deletion (#3728)
* Add form for account deletion

* If avatar or header are gone from source, remove them

* Add option to have SuspendAccountService remove user record, add tests

* Exclude suspended accounts from search
2017-06-14 18:01:27 +02:00
Yamagishi Kazutoshi
a208e7d655 Update React to version v15.6 (#3736) 2017-06-14 16:16:00 +02:00
Yamagishi Kazutoshi
c1b9ae7fc2 Enable useBuiltIns option of transform-object-rest-spread (#3737) 2017-06-14 13:42:00 +02:00
Eugen Rochko
dc8a6244fc Fix #2619 - When redis feed is empty, fall back to database (#3721)
* Fix #2619 - When redis feed is empty, fall back to database

* Use redis value to return feed from database only while RegenerationWorker
hasn't finished running

* Fix specs

* Replace usage of reject!
2017-06-14 13:37:03 +02:00
Sorin Davidoi
0f52e42c2d fix(status): Content jump due to height changes (#3734) 2017-06-13 20:46:21 +02:00
Eugen Rochko
85af2405cf Exclude packs/custom.js from webpack compilation to prevent breakage (#3719)
due to the change in #3373
2017-06-13 03:55:36 +02:00
Eugen Rochko
47ace633dc Simplify getting started links localization. Link "powered by Mastodon" to joinmastodon.org (#3725) 2017-06-13 03:55:28 +02:00
Eugen Rochko
85d5518b6b Fix #3675 - Adjust quality settings of converted GIFs to reduce filesize (#3723) 2017-06-13 00:51:48 +02:00
Eugen Rochko
5104bd7988 Fix unclickable onboardin modal regression (#3724) 2017-06-13 00:39:31 +02:00
m4sk1n
3e425b51fd i18n: minor fix in Polish translation (#3726)
* i18n: minor fix in Polish translation

* i18n
2017-06-12 23:55:32 +02:00
Eugen Rochko
37dbfa4cd7 Unread indicator was invisible behind column header, adjusted (#3720)
* Unread indicator was invisible behind column header, adjusted

* Unread indicator now a CSS pseudo-element

* Adjust flex
2017-06-12 20:02:17 +02:00
Ratmir Karabut
0d23c81662 Update Russian translation (pin) (#3712)
* Update Russian translation (pin)
2017-06-12 12:53:20 +02:00
Yamagishi Kazutoshi
b436b31d5a Regenerate defaultMessages.json (#3709)
follow up #3564
2017-06-12 12:41:19 +02:00
Yamagishi Kazutoshi
72133fbed6 Re-add clear notifications button (#3708)
* Re-add clear notifications button

* remove connect() in column_settings

* one line

* remove unused props
2017-06-12 12:26:23 +02:00
unarist
abbdacedc5 Fix locale related specs (#3707)
* Use I18n.locale instead of ":en"
* Reset I18n.locale value after locale changing tests
2017-06-12 10:58:03 +02:00
Yamagishi Kazutoshi
ddd3251912 Update dependencies for Node.js (#3705)
* Update @storybook/addon-actions to v3.1.2

* Update @storybook/react to v3.1.2

* Update babel-core to v6.25.0

* Update babel-preset-env to v1.5.2

* Update chai to version v4.0.2

* Update extract-text-webpack-plugin to v2.1.2

* Update file-loader to v0.11.2

* Update intersection-observer to v0.3.0

* Update pg to v6.2.4

* Update sinon to v2.3.4

* Update style-loader to v0.18.2

* Update websocket.js to v0.1.10

* Update react-redux-loading-bar to v2.9.2

* yarn upgrade
2017-06-12 10:54:02 +02:00
Eugen Rochko
605e2a417c Fix regression from #3672 - Do not use pipeline around zscore (#3704) 2017-06-12 03:11:12 +02:00
ThibG
f8fe394e7a Fix an error when TagManager.local_url? is called with a bad URI (#3701)
TagManager.local_url? was sometimes called with an URI with a nil host,
leading to a crash in TagManager.local_url?. This fixes moves the
already-existing uri.host.blank? check in front to avoid this case.
2017-06-11 22:53:12 +02:00
Eugen Rochko
2a545e0fb1 Fix #3582 - Update OStatus2 gem (#3699) 2017-06-11 17:47:29 +02:00
Eugen Rochko
ce812466c7 Fix removal of status sending the original status to mentioned users instead of delete Salmon (#3672)
* Fix removal of status sending the original status to mentioned users instead
of delete Salmon, add test

* Create remove_status_service_spec.rb
2017-06-11 17:13:43 +02:00
Eugen Rochko
47bf7a8047 Fix #3665 - Refactor timelines reducer (#3686)
* Move ancestors/descendants out of timelines reducer

* Refactor timelines reducer

All types of timelines now have a flat structure and use the same
reducer functions and actions

* Reintroduce some missing behaviours

* Fix wrong import in reports

* Fix includes typo

* Fix issue related to "next" pagination in timelines and notifications

* Fix bug with timeline's initial state, expandNotifications
2017-06-11 17:07:35 +02:00
René Klačan
85d405c810 Fix Account model deprecation warnings (#3689)
```
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:60)
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:60)
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:60)
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:61)
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:62)
DEPRECATION WARNING: The behavior of `attribute_changed?` inside of after callbacks will be changing in the next version of Rails. The new return value will reflect the behavior of calling the method after `save` returned (e.g. the opposite of what it returns now). To maintain the current behavior, use `saved_change_to_attribute?` instead. (called from block in <class:Account> at /Users/rene/Workspace/personal/ruby/mastodon/app/models/account.rb:63)
```

Here's PR describing changes to Dirty API https://github.com/rails/rails/pull/25337
2017-06-11 17:01:32 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
f596a413ef Localize date in digest and cover NotificationMailer more (#3694)
* Localize date in digest

* Cover NotificationMailer more
2017-06-11 12:04:35 +02:00
Ratmir Karabut
9e53fe5c29 Update Russian translation (#3692) 2017-06-11 10:43:01 +02:00
Yamagishi Kazutoshi
3690f04e4a Remove comments for eslint-disable (#3691) 2017-06-11 10:42:42 +02:00
Yamagishi Kazutoshi
f3e8bc9f8f Refactor UpdateRemoteProfileService (#3690) 2017-06-11 10:41:59 +02:00
René Klačan
dcf0530218 Make sure email is case insensitive on all places (#3688)
When case insensitivity is enabled via devise's `config.case_insensitive_keys` then `.find_for_authentication` method needs to be used instead of `.find_by` because second mentioned returns `nil` when valid email with different cases is passed.

More info https://github.com/plataformatec/devise/wiki/How-To:-Use-case-insensitive-emails
2017-06-11 02:29:08 +02:00
Matt Jankowski
47338bc13d Gem versions, including security-related mail gem update (#3687)
* Update mail to version 2.6.6

* Update aws-sdk to version 2.9.37

* Update capybara to version 2.14.2

* Update oj to version 3.1.0

* Update sidekiq to version 5.0.2

* Update puma to version 3.9.1

* Update sanitize to version 4.5.0

* Update capistrano-rails to version 1.3.0
2017-06-10 20:26:50 +02:00
Jeroen
6fb9726b99 Update NL for 1.4.2 (#3685) 2017-06-10 17:26:01 +02:00
Eugen Rochko
8015fd7600 Improve RTL detection (#3682)
- Use plaintext
- Strip out URLs
- Strip out mentions
- Strip out hashtags
- Strip out whitespace from "overall" count
- Consistent between JS and Ruby
2017-06-10 15:06:50 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
4919b89ab8 Improve default language decision and spec (#3351)
* Improve default language decision

This change allows to takes account of accepted language determined by
the user agent even if the custom default locale of the instance is
configured.

* Cover Localized more

* Fix code style
2017-06-10 09:44:02 +02:00
Matt Jankowski
2925372ff4 Move create/destroy actions for api/v1/statuses to namespace (#3678)
Each of mute, favourite, reblog has been updated to:

- Have a separate controller with just a create and destroy action
- Preserve historical route names to not break the API
- Mild refactoring to break up long methods
2017-06-10 09:39:26 +02:00
m4sk1n
778430b54a i18n: Minor fixes in Polish translation (#3674)
* i18n

* i18n

* i18n

* i18n

* i18n
2017-06-09 23:08:09 +02:00
Matt Jankowski
5282ba862a Move reblogged_by and favourited_by actions out of api/v1/statuses and into unique controllers (#3646)
* Add specs for api statuses routes

* Update favourited_by and reblogged_by api routes

* Move methods into new controllers

* Use load_accounts methods to simplify index actions

* Clean up load_accounts methods

* Clean up link header generation

* Check for link headers in specs

* Remove unused actions from api/v1/statuses controller

* Remove specs for moved actions
2017-06-09 14:12:40 -04:00
Eugen Rochko
0464602978 Fix issue with some Node.js versions not having Array.prototype.includes (#3667)
by using Array.prototype.indexOf instead
2017-06-09 19:46:33 +02:00
Eugen Rochko
9b03cf0ddd Fix #3658 - Update RTL styles (#3669) 2017-06-09 19:46:25 +02:00
Eugen Rochko
cdff1da901 Correct validators so that existing error messages would look correct (#3668) 2017-06-09 19:46:01 +02:00
m4sk1n
1a065fb146 i18n: updated Polish translation (#3670) 2017-06-09 19:15:55 +02:00
Matt Jankowski
022008a2a6 Language detection defaults to nil (#3666)
* Default to nil for statuses.language

* Language detection defaults to nil instead of instance UI default
2017-06-09 18:09:37 +02:00
Clworld
a3715598cc adjust the size of 'column-header__back-button' (retry) (#3662) 2017-06-09 16:22:28 +02:00
Yamagishi Kazutoshi
1be48dd805 Refactor views/admin/reports/show.html.haml (#3656) 2017-06-09 15:08:06 +02:00
Yamagishi Kazutoshi
6384041d17 Add includes to Report#statuses (#3655) 2017-06-09 15:07:02 +02:00
Yamagishi Kazutoshi
140e73bc82 Check ready state of document in public pages (#3652)
* Check ready state of document in public pages

* add check interactive
2017-06-09 15:06:38 +02:00
ふぁぼ原
e3fae6f52c adjust the size of column-header__back-button (#3654) 2017-06-09 15:05:26 +02:00
unarist
65d8c73bae Add Japanese translation for #3640 (#3650) 2017-06-09 03:14:15 +02:00
Eugen Rochko
177dd8bb53 Fix regression from #3592 - validation condition nesting (#3644) 2017-06-08 19:10:48 +02:00
Eugen Rochko
380b20eed6 Bump version to 1.4.2 2017-06-08 15:30:43 +02:00
Eugen Rochko
c207b4bb33 Fix db:seed - only run some validations when the field was changed (#3592)
* Fix db:seed - only run some validations when the field was changed

* Add tests
2017-06-08 09:22:01 -04:00
Eugen Rochko
b87eb8ea14 Fix #3378 - If favourite/reblog already exists, return it instead of failing (#3641) 2017-06-08 15:07:39 +02:00
Eugen Rochko
8902e265b4 Add explit admin actions to (re)subscribe/unsubscribe remote accounts (#3640)
* Add explit admin actions to (re)subscribe/unsubscribe remote accounts
and re-download avatar/header

* Improve how admin NSFW toggle looks
2017-06-08 14:58:22 +02:00
nullkal
b8ea28d6d0 Support multiple trusted proxy ip addresses (#3639)
* Support multiple trusted proxy ip addresses

* correct coding style
2017-06-08 14:33:28 +02:00
ThibG
f741673638 Fixes #3605 by returning account from database in case of race condition (#3606) 2017-06-08 13:40:11 +02:00
Yamagishi Kazutoshi
0a0b9a271a Improve RuboCop rules (compatibility to Code Climate) (#3636)
08f8de84eb/Gemfile.lock (L38)
Code Climate is using RuboCop v0.46.0.

Change several rules to maintain compatibility.
2017-06-08 13:24:28 +02:00
Yamagishi Kazutoshi
7d2b4186c3 Add Japanese translations (#3635) 2017-06-08 13:23:56 +02:00
m4sk1n
90689190a3 i18n: Update Polish translation (#3637) 2017-06-08 13:23:40 +02:00
Sorin Davidoi
8acadeea76 fix: Warn if JavaScript is disabled (#3634) 2017-06-08 00:52:56 +02:00
Eugen Rochko
75c6513c67 Add rake task to prepare database for foreign keys introduced by #3562 (#3614)
* Add rake task to prepare database for foreign keys introduced by #3562

* Fix typo

* Do not delete OAuth values where NULL values may be permitted

* Fix typo
2017-06-07 20:16:53 +02:00
Matt Jankowski
73540ffe6b Clean up for api/base controller (#3629)
* Move ApiController to Api/BaseController

* API controllers inherit from Api::BaseController

* Add coverage for various error cases in api/base controller
2017-06-07 20:09:25 +02:00
jeroenpraat
92bb166246 Rest of 2FA translated + small fix (#3630) 2017-06-07 20:08:34 +02:00
Sorin Davidoi
8cf8ce4ac0 fix(components/autosuggest_textarea): Race condition regarding onBlur (#3631) 2017-06-07 20:05:53 +02:00
unarist
0f1b1d78b1 Use "match_array" only for order independent assertions (#3626) 2017-06-07 12:59:28 -04:00
Eugen Rochko
d3bbef27e7 Fix broken screenshot 2017-06-07 17:53:47 +02:00
Matt Jankowski
f0634ba876 Coverage improvement and concern extraction for rate limit headers in API controller (#3625)
* Coverage for rate limit headers

* Move rate limit headers methods to concern

* Move throttle check to condition on before_action

* Move match_data variable into method

* Move utc timestamp to separate method

* Move header setting into smaller methods

* specs cleanup
2017-06-07 17:23:26 +02:00
Yamagishi Kazutoshi
1d68fe1a60 Fix Code Climate failed (regression from #3622) (#3624) 2017-06-07 15:57:59 +02:00
unarist
6bd6dcf6df Allow "class" attribute on the "a" tag in sanitization (#3623)
This preserves `<a ... class="u-url mention">` from other Mastodon instances.
2017-06-07 15:57:30 +02:00
ThibG
28d2920472 Fixes #3388 by moving re-entrant shared_status_from_xml before transaction block (#3622)
Steps to reproduce the original issue:
1. Have two remote accounts, A that you don't follow, and B that you follow.
2. Have A post a toot and reply to it.
3. Boost A's reply from remote account B.

This used to cause the local instance to get A's reply but fail to link it to
the original post.
2017-06-07 12:28:16 +02:00
Yamagishi Kazutoshi
34bfea8bbf Small changes to japanese translation (#3620) 2017-06-07 10:15:35 +02:00
STJrInuyasha
2d91944285 Don't show business e-mail if it's blank (#3619) 2017-06-07 09:57:47 +02:00
Daigo 3 Dango
0026ba2751 Update nokogumbo to 1.4.13 (#3617)
$ bundle update --source nokogumbo# Please enter the commit message for your changes. Lines starting

nokogumbo 1.4.11 and 1.4.12 don't work on Heroku.
2017-06-06 20:43:02 +02:00
Eugen Rochko
b623dd12c1 Use preview image in <ImageLoader /> to provide immediate visual feedback (#3595)
before the full-size image is loaded
2017-06-06 19:30:17 +02:00
Eugen Rochko
722d152082 Fix #3063 - Add dynamic app manifest (#3563)
* Fix #3063 - Add dynamic app manifest

* Added short_name

* Add background_color
2017-06-06 19:29:42 +02:00
ふぁぼ原
7623766241 Add regex filters on the community timeline and the public timeline. (#3564)
* Add regex filter on the community timeline and the public timeline

* correcting

* Adjust the height of header buttons

* Remove trailing spaces

* Remove trailing spaces

* Solve some code duplication

* reset the state of the locale files in app/javascript/mastodon/locales

* adjust to upstream

* adjust to upstream

* change keys of locale settings
2017-06-06 16:56:10 +02:00
unarist
e34c5a3503 Fix 500 errors on searching invalid URLs (#3613) 2017-06-06 16:44:48 +02:00
unarist
004672aa6c Fix tag search order and not to use tsvector (#3611)
* Sort results by the name
* Switch search method to simple `LIKE` matching instead of tsvector/tsquery

Previously we used scores from ts_rank_cd() to sort results, but it didn't work
because the function returns same score for all results. It's not for calculate
similarity of single words. Sometimes this bug even push out exact matching tag
from results.

Additionally, PostgreSQL supports prefix searching with standard btree index.
Using it offers simpler code, but also less index size and some speed.
2017-06-06 16:07:06 +02:00
Yamagishi Kazutoshi
ad4a28f4f6 Refactor translationRunner.js (#3604)
- Use yargs instead of minimist
- Simplify validators
- Fix typo (RFC5626 -> RFC5646)
2017-06-06 13:31:57 +02:00
Yamagishi Kazutoshi
d8ae3efec3 Improve ESLint rules for JSX (#3608)
* Add react/no-string-refs ESLint rule

* Add react/jsx-boolean-value ESLint rule

* Add react/jsx-closing-bracket-location ESLint rule

* Add react/jsx-indent ESLint rule

* Add react/jsx-curly-spacing ESLint rule

* Add react/jsx-equals-spacing ESLint rule

* Add react/jsx-first-prop-new-line ESLint rule

* Add react/jsx-no-duplicate-props ESLint rule

* Add react/jsx-tag-spacing ESLint rule
2017-06-06 13:20:07 +02:00
Yamagishi Kazutoshi
cd81a1c52a Add missing key attribute to .search-results__hashtag (#3607) 2017-06-06 13:19:29 +02:00
May Kittens Devour Your Soul
dcf73ddeff Update hr.json (#3609) 2017-06-06 13:19:05 +02:00
Yamagishi Kazutoshi
d81b706f12 Fix typo (storyboard -> storybook) (#3603) 2017-06-06 04:07:34 +02:00
m4sk1n
30fa5fe1a4 i18n: updated Polish translation (#3597)
* i18n: updated Polish translation

* i18n: updated Polish translation

btw it would be nice to have master-based Mastodon instance (even isolated from others) to test translation.
2017-06-06 03:59:13 +02:00
Yamagishi Kazutoshi
7a7bfa5170 Add quotes ESLint rules (#3602)
* Add quotes ESLint rule

* Add jsx-quotes ESlint rule

* Sort ESLint rules
2017-06-06 03:56:36 +02:00
Yamagishi Kazutoshi
e969c78645 Disable ESLint rule jsx/anchor-has-content (#3601) 2017-06-06 03:55:56 +02:00
ThibG
7adac1bc51 Try fixing ThreadResolveWorker calls (#3599)
* Try fixing ThreadResolveWorker calls

From my understanding of ActiveRecord, a transaction is commited as soon as
the exit of the outmost ActiveRecord.transaction block. However, inner
transaction blocks will exit without the transaction being commited.

In this case, ThreadResolveWorker were fired *within* a transaction block,
so moving the call out of it should do the trick. However, this is somewhat
fragile, as this whole codepath could be called within yet another transaction.

* Set status thread within the transaction block if it is immediately available from database
2017-06-06 00:09:14 +02:00
Naoki Kosaka
e859d6f259 Fix LoadMore in Notifications. (#3590) 2017-06-05 19:18:26 +02:00
Naoki Kosaka
a0880edc6e Fix (PR #3585) Add hasMore to propTypes and cover handleScroll. (#3589) 2017-06-05 18:18:56 +02:00
unarist
61fcdbbf7e Add back button to hashtag timeline again (#3587) 2017-06-05 17:10:40 +02:00
Shunsuke Michii
43af695ba1 Add th.json. (#3588) 2017-06-05 17:02:41 +02:00
IkUrA
facd90e7a6 Add streaming_api_base_url to /api/v1/instance (#3556)
* Add streaming_api_base_url to /api/v1/instance

* Adjust spaces

* nested view

* re-adjust spaces
2017-06-05 16:37:44 +02:00
Matt Jankowski
6201f96b8a Introduce StatusThreadingConcern (#3490)
* Add a StatusFilter class to identify visibility of statuses by accounts

* Extract StatusThreadingConcern from Status

* Clarify purpose of checking for nil account
2017-06-05 16:07:44 +02:00
unarist
c26cea262b Prevent pinned columns from scroll to top on URL changing (#3586) 2017-06-05 15:20:46 +02:00
Naoki Kosaka
1f1d6bf2a0 Fix LoadMore in following and followers. (#3585) 2017-06-05 14:13:20 +02:00
Eugen Rochko
4c06d1cb24 Fix #3550 - Add all missing foreign keys (#3562)
* Fix #3550 - Add all missing foreign keys

* Add missing foreign keys
2017-06-05 13:24:00 +02:00
Daigo 3 Dango
2985d08951 Redirect to streaming_api_base_url (#3579)
* Redirect to streaming_api_base_url

When Rails receives a request to streaming API, it most likely
means that there is another host which is configured to respond
to it. This is to redirect clients to that host if
`STREAMING_API_BASE_URL` is set as another host.

* Use the new Ruby 1.9 hash syntax
2017-06-05 12:09:29 +02:00
Yamagishi Kazutoshi
66ca7157db Add support key shortcut to Onboarding Modal (#3517)
* Add support key shortcut to Onboarding Modal

* this.state.pages -> this.pages
2017-06-05 10:09:14 +02:00
Yamagishi Kazutoshi
4addf051d4 Fix broken embed page (#3577) 2017-06-05 10:08:31 +02:00
Yamagishi Kazutoshi
ab914ce6d5 Add OnboadingModal story (#3578) 2017-06-05 10:08:07 +02:00
Yamagishi Kazutoshi
6a4b224397 Fix randomly fail (regression from #3560) (#3580) 2017-06-05 10:03:36 +02:00
Yamagishi Kazutoshi
6adbd114c1 Skip image length check (regression from #3528) (#3581) 2017-06-05 10:03:01 +02:00
René Klačan
037f96c5ae Don't follow account if it's already followed (#3575)
Closes https://github.com/tootsuite/mastodon/issues/3102
2017-06-05 03:24:18 +02:00
René Klačan
f54dca06a9 Add migration versions (#3574)
Since Rails 5.1 missing migration version results in following error:

```
StandardError: Directly inheriting from ActiveRecord::Migration is not supported. Please specify the Rails release the migration was written for:
```

This PR fixes all migration files.
2017-06-05 02:43:02 +02:00
Quent-in
370fa70924 l10n update for occitan language (#3557)
* i18n Update : Add preference setting for delete toot modal

Adding a line for "Add preference setting for delete toot modal"

* i18n update for pin/unpin

Update to add two more translations

* i18n update to have the dates in plain occitan

* Removed the blank line

* %{selft} back in the translation
2017-06-05 01:31:10 +02:00
Matt Jankowski
5be1214c26 Gem version bumps (#3524)
* Update annotate to version 2.7.2

* Update puma to version 3.9.0

* Update aws-sdk to version 2.9.28

* Update bootsnap to version 1.0.0

* Update nio4r to version 2.1.0

* Update nokogumbo to version 1.4.12

* Update oj to version 3.0.11

* Update pkg-config to version 1.2.3

* Update rubocop to version 0.49.1

* Update sidekiq-scheduler to version 2.1.5
2017-06-05 01:10:13 +02:00
Eugen Rochko
f7a30e2fae Added support for configurable reserved usernames (fix of #1382) (#3566)
* Added support for configurable reserved usernames

* Added reserved usernames from mastodon issue 1355

* Fix reserved usernames
2017-06-05 01:03:45 +02:00
Yamagishi Kazutoshi
3f815b2052 Add date to ignore_missing and ignore_unused in config/i18n-tasks.yml (#3572) 2017-06-05 01:02:19 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
defe4f9bc3 Cover WebfingerResource more (#3560) 2017-06-04 17:13:37 +02:00
Yamagishi Kazutoshi
943775fd90 Update dependencies of Node.js (#3561)
* Update axios to version 0.16.2

* Update css-loader to version 0.28.4

* Update postcss-smart-import to version 0.7.4

* Update react-immutable-pure-component to version 0.0.5

* Update stringz to version 0.2.1

* Update style-loader to version 0.18.1

* Update websocket.js to version 0.1.9

* yarn upgrade
2017-06-04 17:13:21 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
42844df966 Spec ScopedSettings (#3559) 2017-06-04 17:07:39 +02:00
Yamagishi Kazutoshi
b0fe58dc69 Upgrade storybook to v3 (#3558) 2017-06-04 16:26:07 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
e07b57852e Remove some code in TagManager and spec (#3547)
* Do not fall back to StreamEntry if object_type is unavailable in TagManager

Since 6d6a429af8, when Status, the only model
with stream_entry, and StreamEntry got its own logic in uri_for and
url_for, the purpose of the fallbacks to activity_type of StreamEntry
became unclear.

This commit removes the fallbacks. When adding another model with
stream_entry in future, consider to update uri_for and url_for.

* Cover TagManager more
2017-06-04 16:14:25 +02:00
m4sk1n
7c7c18fdea i18n: Updated Polish translation (#3555) 2017-06-04 15:18:42 +02:00
lindwurm
a84664026e l10n: ja: Change about/more link text (#3539)
ref: #3538 ("Extended information" -> "About this instance") and #3519

Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-06-04 15:00:15 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
02a0fd5b64 Spec InlineRablScope (#3542) 2017-06-04 15:00:08 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
6505a42be0 Spec HashObject (#3544) 2017-06-04 14:59:52 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
e674608d10 A minor change for ProviderDiscovery and spec (#3543)
* Do not default the format in ProviderDiscovery

The format should be determined when discovering, as it is in the current
implementation, and it is a flaw if it is not determined.

* Spec ProviderDiscovery
2017-06-04 14:59:40 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
c7af8cbc90 Remove some arguments of Formatter.instance.format and spec (#3541)
* Remove some arguments of Formatter.instance.format

* Improve spec for Formatter
2017-06-04 14:58:57 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
9475fbae78 Spec Extractor (#3540) 2017-06-04 14:57:02 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
00e61d6807 Spec action verification of StreamEntryFinder (#3549) 2017-06-04 14:56:31 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
19084d3c6c Remove Targetable (#3548) 2017-06-04 14:56:10 +02:00
Naoki Kosaka
e014bf8ed0 Fix limit_param in favourites_controller.rb (#3553) 2017-06-04 14:52:26 +02:00
Yamagishi Kazutoshi
f6e2309e70 Fix column buttons overflow in Japanese (#3552) 2017-06-04 14:52:02 +02:00
Yamagishi Kazutoshi
9d2154c4ab Add Japanese translations (pin) (#3551)
* Add Japanese translations (pin)

* "ピン留め" is more general
2017-06-04 14:51:35 +02:00
unarist
1dfd27a028 Fix all icons in the column header being hilighted (#3554) 2017-06-04 14:51:06 +02:00
Mingye Wang
b97ebaf620 en.json: change about/more link text to "About this instance" (#3538)
This change follows #3519, which does the same for the Chinese variants. Or should it be simply "About"?
2017-06-04 04:25:18 +02:00
Eugen Rochko
8ee2eb5d2e Allow mounting arbitrary columns (#3207)
* Allow mounting arbitrary columns

* Refactor column headers, allow pinning/unpinning and moving columns around

* Collapse animation

* Re-introduce scroll to top

* Save column settings properly, do not display pin options in
single-column view, do not display collapse icon if there is
nothing to collapse

* Fix one instance of public timeline being closed closing the stream
Fix back buttons inconsistently sending you back to / even if history exists

* Getting started displays links to columns that are not mounted
2017-06-04 01:39:38 +02:00
masarakki
20b647020b refocus-after-toot (#3537) 2017-06-04 01:22:37 +02:00
takayamaki
3eedad2737 change sidekiq queueing to bulk push (#3536) 2017-06-04 00:11:15 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
ce7c0def88 Remove redundant code in AtomSerializer and spec (#3528)
* Remove redundant status.reply? in AtomSerializer#object

* Cover AtomSerializer more
2017-06-03 20:51:08 +02:00
Clworld
dab8fc4584 Execute PushUpdateWorker only for accounts who uses StreamingAPI just now. (#3278)
* Add redis key "subscribed:timeline:#{account.id}" to indicate active streaming API listeners exists.

* Add endpoint for notification only stream.

* Run PushUpdateWorker only for users uses Streaming API now.

* Move close hander streamTo(Http/Ws) -> stream(Http/Ws)End (Deal with #3370)

* Add stream type for stream start log message.
2017-06-03 20:50:53 +02:00
Yamagishi Kazutoshi
8a597f0138 Cache assets in travis (#3532) 2017-06-03 15:13:12 +02:00
Nolan Lawson
3363f2f4d6 Fix isIntersecting in Chrome (#3525) 2017-06-03 14:43:10 +02:00
Mingye Wang
c7f2d6af55 zh-cn&tw.json: "extended info" -> "about this site" (#3519)
* zh-cn.json: "additional info" -> "more info"

This commit changes the "extended info" (about/more) text to something that translates to "more info", as "additional info" in zh can sound like appending things to the (ugh) navbar, I guess.

Or should I just change it to "about this site" (关于本站)?

* zh-cn.json: navbar.info -> "about this site"

* zh-臺灣.json: navbar.info -> "about this site"
2017-06-03 14:42:47 +02:00
Yamagishi Kazutoshi
e878ddb7c0 Fix spec for #2388 (#3526) 2017-06-03 14:40:55 +02:00
Yamagishi Kazutoshi
336f0b0823 Remove WarmCacheService (#3527)
WarmCacheService is no longer used (removed with 5442083b3c ).
2017-06-03 14:40:47 +02:00
Yamagishi Kazutoshi
3ea3f24a02 Change toggle state when click label (#3530) 2017-06-03 14:40:24 +02:00
ThibG
d567a382e3 Ensure well_known controllers use WEB_DOMAIN by including RoutingHelper (#2388)
This fixes #2375.
2017-06-02 22:21:36 +02:00
Clworld
18fe77084f bump rails version in Gemfile: '~> 5.0.0' -> '~> 5.1.0' (#3523) 2017-06-02 20:11:13 +02:00
Naoki Kosaka
dc253ea234 Ignore packs folder when COPY . /mastodon (#3522) 2017-06-02 18:09:28 +02:00
Sorin Davidoi
9304114b57 Ignore .idea folder (#3516)
Used by Intellij IDEA / WebStorm / RubyMine.
2017-06-02 16:19:11 +02:00
Matt Jankowski
1fd5251376 Add index to media_attachments.account_id (#3510) 2017-06-02 16:18:54 +02:00
Nolan Lawson
edddc7c791 Enable stats.json analysis with Webpack Visualizer (#3509) 2017-06-02 03:49:56 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
10768aa204 Spec response for forgery (#3248)
Remove protect_from_forgery in ApiController, which is disabled by the
following skip_before_action, as well.
2017-06-01 20:56:55 +02:00
Akihiko Odaki (@fn_aki@pawoo.net)
e98559c3ff Resolve custom application stylesheet with Webpack (#3373)
This implementation is a bit smaller and still has the following benefits:

* No need of app/javascript/packs/custom.js
For custom stylesheet, it typically has only
"require('../styles/custom.scss')" and is redundant.

* No need to extract vendor stylesheet to another asset
Extracting vendor stylesheet could be forgotten by developers who do not
use custom stylesheet.
2017-06-01 20:56:32 +02:00
Matt Jankowski
2212dc4aaa Update Rails to version 5.1.1 (#3121)
* Update rails to version 5.1.1

* Run `rails app:update`

* Remove the override of polymorphic activity relationship

* Silence warning about otp_secret attribute being unknown to rails

* We will only introduce form_with where we want to use remote data
2017-06-01 20:53:37 +02:00
Daniel Hunsaker
e1fdac3e9a [nanobox] Add python for node-gyp (#3491)
Needed since merge of #3067.
2017-06-01 17:33:57 +02:00
Yamagishi Kazutoshi
1162f61ca3 Remove unused loaders of webpack (#3495) 2017-06-01 17:27:35 +02:00
Yamagishi Kazutoshi
39ea5c0e2e Improve tests for JavaScript (#3496)
- Upgrade dependencies
    - chai (3.5.0 -> 4.0.1)
    - chai-enzyme (0.6.1 -> 0.7.1)
    - sinon (2.2.0 -> 2.3.2)
- Change extensions from .jsx to .js
- Don't assign `React` to `global`
- Check code format using ESLint
2017-06-01 17:27:15 +02:00
Yamagishi Kazutoshi
509b0cfafc Add scenarios for log in (#3497) 2017-06-01 17:25:59 +02:00
Yamagishi Kazutoshi
fda5c699c2 Add ESLint rule (object-curly-spacing) (#3498) 2017-06-01 17:25:10 +02:00
Matt Jankowski
cb7ee4698f Rubocop changes (#3501)
* Update renamed rubocop configuration options

* Remove duplicate rubocop configuration, sort options
2017-06-01 17:24:30 +02:00
Matt Jankowski
d010e270e6 Remove usernames and hashtags from language detection (#3503)
* Add failing specs for hashtag and username extraction in language detector

* Remove usernames and hashtags from text before language detection

* Handle multiple instances of special case, and reduce whitespace
2017-06-01 09:29:14 -04:00
Matt Jankowski
d1e08bd38c Handle nil and blank cases in Account finders (#3500) 2017-06-01 08:20:36 -04:00
unarist
dbccdcc1b1 Focus the submit button on the boost modal (#3494)
Focus the submit button when boost modal is opened.
2017-06-01 04:20:10 +02:00
Matt Jankowski
5c63523972 Spec coverage and refactor for the api/v1/accounts controllers (#3451) 2017-05-31 21:36:24 +02:00
Matt Jankowski
de4681b2be Move admin/pubsubhubbub controller to admin/subscriptions (#3442) 2017-05-31 20:39:35 +02:00
Matt Jankowski
a132332b86 Add Instance class to list admin records (#3443) 2017-05-31 20:38:44 +02:00
Matt Jankowski
b25e42a77f Misc tidying and clean ups (#3445)
* Remove trailing whitespace in i18n mailers

* Use query methods instead of #present? on AR attributes

* Delegate Status#account_domain method

* Delegate Mention #account_username and #account_acct methods
2017-05-31 20:38:17 +02:00
Matt Jankowski
5236a62861 Improve spec coverage and clean up api/v1/blocks controller (#3464) 2017-05-31 20:34:51 +02:00
Matt Jankowski
0f155829b7 Improve spec coverage and clean up api/v1/follow_requests controller (#3465) 2017-05-31 20:32:11 +02:00
Matt Jankowski
84dda45df9 Improve spec coverage and clean up api/v1/domain_blocks controller (#3466) 2017-05-31 20:31:14 +02:00
Matt Jankowski
9c7505489f Refactor api/v1/notifications controller (#3470) 2017-05-31 20:30:55 +02:00
Matt Jankowski
75cad1d9d6 Improve spec coverage and clean up api/v1/favourites controller (#3472) 2017-05-31 20:30:39 +02:00
Matt Jankowski
2cc3111a77 Expand spec coverage and refactor the Account.find_ methods (#3485)
* Move specs for account finder methods to concern spec

* Move account finder methods to concern

* Improve spec wording

* Use more explicit comparison to ensure correct return value

* Add coverage for .find_local! and .find_remote!

* Add some methods to the finder

* Use arel on matching_username method

* Avoid ternary in matching domain method

* Simplify finder methods

* Use an AccountFinder class to simplify lookup
2017-05-31 20:28:45 +02:00
Matt Jankowski
bf811e4d4a Improve spec coverage and clean up api/v1/mutes controller (#3481) 2017-05-31 20:27:34 +02:00
Matt Jankowski
d6774d2ca3 Refactor and spec coverage for api/v1/timelines actions (#3482) 2017-05-31 20:27:17 +02:00
caasi Huang
bd669e3907 Update zh-TW.json (#3480)
* Update zh-TW.json

* Update `search_results.total`
2017-05-31 18:46:57 +02:00
Yamagishi Kazutoshi
1a4860a57a Hold value of I18n.locale with ApplicationHelperSpec (#3474) 2017-05-31 17:09:28 +02:00
Yamagishi Kazutoshi
41fa53253c Keep ENV['LOCAL_HTTPS'] with ApplicationControllerSpec (fix random fail) (#3479)
* Keep ENV['LOCAL_HTTPS'] with ApplicationControllerSpec (fix random fail)

* use climate_control
2017-05-31 17:09:17 +02:00
Nolan Lawson
c00ead8a72 Remove react-imageloader (#3423)
* Remove react-imageloader

* add eslint-disable-line

* improve image loading experience

* remove unneeded import

* use PureComponent

* Use componentWillMount instead of constructor
2017-05-31 17:07:25 +02:00
unarist
e49dc6a06e Fix load more on account timelines (regression from #3311) (#3475)
This prevents `next` state from being overridden on the loading *new* statuses.
2017-05-31 15:30:26 +02:00
Nolan Lawson
0e12a8dab9 Improve scheduling of requestIdleCallback tasks (#3477) 2017-05-31 15:11:33 +02:00
alpaca-tc
3652a39de0 Account.find_remote should be raise ActiveRecord::RecordNotFound (#3476) 2017-05-31 15:10:26 +02:00
Matt Jankowski
79335e46fd Refactor api/v1/apps controller (#3471) 2017-05-30 21:16:28 -04:00
Matt Jankowski
7c6e02aaf3 Refactor api/v1/reports controller (#3469) 2017-05-30 21:13:31 -04:00
Matt Jankowski
7f55430652 Refactor api/v1/search controller (#3468) 2017-05-30 21:11:54 -04:00
Matt Jankowski
8235623362 Improve spec coverage and clean up api/v1/media controller (#3467) 2017-05-30 21:11:29 -04:00
Matt Jankowski
83435c49ea Clean up api/subscriptions controller (#3448) 2017-05-31 02:15:09 +02:00
spla
93de41b39b Catalan language updates (#3454)
* Add Catalan language

* Add Catalan language

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update ca.json

* Update settings_helper.rb

* Update mastodon.js

* Update index.js

* Update application.rb

* Update ca.yml

* removed extra spaces at line 225

* Catalan translation update

added activerecord.ca.yml

* Update activerecord.ca.yml

Done

* Updated activerecord.ca.yml

* Catalan language updated

* Catalan language updated

* Catalan language updated

* Catalan language updated

* Catalan language updated
2017-05-31 02:14:52 +02:00
Yamagishi Kazutoshi
b1d4b74a44 Change PureComponent to ImmutablePureComponent (#3460)
* Change PureComponent to ImmutablePureComponent

Change PureComponent to ImmutablePureComponent in AttachmentList.

* rm React.
2017-05-31 02:14:26 +02:00
Yamagishi Kazutoshi
bfdf47bc98 Add zh-TW.json (#3459) 2017-05-30 23:09:02 +02:00
Jack Jennings
33f669a5f8 Add status destroy authorization to policy (#3453)
* Add status destroy authorization to policy

* Create explicit unreblog status authorization
2017-05-30 22:56:31 +02:00
Matt Jankowski
3576fa0d59 Improve api oembed controller (#3450)
* Add StreamEntryFinder class to parse URLs

* Use StreamEntryFinder and clean up api/oembed controller
2017-05-30 16:30:06 -04:00
Matt Jankowski
1dcfb90202 Clean up api/salmon controller (#3449) 2017-05-30 16:28:58 -04:00
Jack Jennings
22cf18e16f Fix incorrect visibility setter in StatusPolicySpec (#3456) 2017-05-30 22:14:32 +02:00
Matt Jankowski
0ebe7d6d23 Remove exports/base controller in favor of shared concern (#3444) 2017-05-30 19:06:01 +02:00
Chris
23081bb299 added 'https://' to CDN_HOST variable example (#3446) 2017-05-30 18:39:28 +02:00
Yamagishi Kazutoshi
4c7fe48c40 Add "private: true" to package.json (#3441) 2017-05-30 16:11:45 +02:00
Naouak
499cc7b803 Fix webpack building on Windows (#3426)
* Path should not be constructed manually. Use path.join to ensure compatibility.

* Path should not be constructed manually. Use path.join to ensure compatibility.

* Fix regexp.

* Fix my own stupidity.
I forgot to check outside my test script the regexp...
2017-05-30 15:30:59 +02:00
Akihiko Odaki
7db98aa70e Refactor User and spec (#3431)
* Protect send_devise_notification of User

* Improve spec for User
2017-05-30 15:28:56 +02:00
Jack Jennings
e031fd60ad Move status reblog authorization into policy (#3425) 2017-05-30 15:16:14 +02:00
Yamagishi Kazutoshi
bc4fad9e22 Change libraries path to relative (#3433) 2017-05-30 15:13:04 +02:00
Yamagishi Kazutoshi
5ac4d677e9 Remove unused React Storybook addon (#3434) 2017-05-30 15:12:12 +02:00
Nolan Lawson
b42bdd80e8 Extract polyfill loading into single module (#3421) 2017-05-30 15:11:15 +02:00
Akihiko Odaki
76fa9d2488 Use around hook to restore context in InstancePresenter spec (#3430) 2017-05-30 09:03:35 -04:00
Akihiko Odaki
dfc43a6d3d Use around hook to restore context in InstanceHelper spec (#3429) 2017-05-30 06:32:33 -04:00
Akihiko Odaki
67bc58dd60 Use around hook to restore context in Admin::SettingsController spec (#3428) 2017-05-30 06:32:09 -04:00
Akihiko Odaki
2d39560dc1 Use around hook to restore context in ApplicationHelper spec (#3432) 2017-05-30 06:29:48 -04:00
Yamagishi Kazutoshi
c49ff7395e Run bundle command (follow up #3403) (#3427) 2017-05-30 03:04:44 +02:00
Yamagishi Kazutoshi
e0ada97770 Update dependencies of Node.js (#3067)
* Update autoprefixer to version 7.1.0

* Update axios to version 0.16.1

* Update babel-cli to version 6.24.1

* Update babel-eslint to version 7.2.3

* Update babel-preset-react to version 6.24.1

* Update coffee-script to version 1.12.6

* Update css-loader to version 0.28.1

* Update express to version 4.15.2

* Update js-yaml to version 3.8.4

* Update mocha to version 3.4.1

* Update jsdom to version 10.1.0

* Update npmlog to version 4.1.0

* Update postcss-smart-import to version 0.7.0

* Update postcss-loader to version 2.0.5

* Update pg to version 6.1.5

* Update prop-types to version 15.5.10

* Update rails-ujs to version 5.1.1

* Update redis to version 2.7.1

* Update sass-loader to version 6.0.5

* Update stringz to version 0.2.0

* Update webpack to version 2.5.1

* Update style-loader to version 0.17.0

* Update sinon to version 2.2.0

* Update react-motion to version 0.5.0

* Update react-notification to version 6.7.0

* Update react-redux-loading-bar to version 2.9.0

* Update react-intl to version 2.3.0

* Update redux-immutable to version 4.0.0

* Update reselect to version 3.0.1

* Update react-toggle to version 3.0.1

* Update react-simple-dropdown to version 3.0.0

* Update react-router to version 3.0.5

* Update react-router-scroll to version 0.4.2

* Update react-toggle to version 4.0.1

* yarn upgrade
2017-05-29 18:23:28 +02:00
Jack Jennings
3a2003ba86 Extract authorization policy for viewing statuses (#3150) 2017-05-29 18:22:22 +02:00
unarist
9a81be0d37 [RFC] Return 401 for an authentication error on WebSockets (#3411)
* Return 401 for an authentication error on WebSocket

* Use upgradeReq instead of a custom object
2017-05-29 18:20:53 +02:00
Matt Jankowski
5e2c5e95b6 Version bumps for non-rails gems (#3398)
* Update xpath to version 2.1.0

* Update aws-sdk to version 2.9.25

* Update oj to version 3.0.10

* Update brakeman to version 3.6.2

* Update rufus-scheduler to version 3.4.2

* Update doorkeeper to version 4.2.6

* Update rubocop to version 0.49.0
2017-05-29 18:18:06 +02:00
Nolan Lawson
34a93ccf57 Add IntersectionObserverWrapper to cut down on re-renders (#3406) 2017-05-29 18:17:51 +02:00
Akihiko Odaki
922fb74197 Remove methods from ObfuscateFilename and spec (#3347)
* Remove methods from ObfuscateFilename

* Spec ObfuscateFilename
2017-05-29 18:14:16 +02:00
Akihiko Odaki
7bf2d6cb06 Spec Auth::ConfirmationsController (#3348) 2017-05-29 18:13:11 +02:00
Akihiko Odaki
11e5c965c3 Spec AccountControllerConcern (#3349) 2017-05-29 18:12:54 +02:00
Akihiko Odaki
34157d118c Cover Admin::ReportsController more (#3346) 2017-05-29 18:12:34 +02:00
Akihiko Odaki
7b92950f1c Cover InstancesController more (#3342) 2017-05-29 18:12:17 +02:00
Akihiko Odaki
97d7028c31 Cover Admin::SuspensionsController more (#3350) 2017-05-29 18:11:16 +02:00
Akihiko Odaki
a7f2961621 Spec Auth::PasswordsController (#3352) 2017-05-29 18:10:50 +02:00
Akihiko Odaki
00dda99789 Spec Admin::ResetsController calls send_reset_password_instructions (#3354) 2017-05-29 18:09:17 +02:00
Akihiko Odaki
2e27ce3b61 Spec #destroy feature of Admin::TwoFactorAuthenticationsController (#3355) 2017-05-29 18:08:58 +02:00
Akihiko Odaki
2c10c5a069 Coever Admin::SilencesController more (#3356) 2017-05-29 18:08:42 +02:00
Akihiko Odaki
bd4dd4c4a0 Cover Settings::ExportsController more (#3358) 2017-05-29 18:08:26 +02:00
Akihiko Odaki
7d33b60f3f Cover Oauth::AuthorizedApplicationsController (#3359) 2017-05-29 18:08:05 +02:00
Akihiko Odaki
aecce5694b Cover Oauth::AuthorizationsController more (#3361) 2017-05-29 18:07:39 +02:00
Akihiko Odaki
0e4ca51951 Cover Settings::TwoFactorAuthenticationsController more (#3376) 2017-05-29 18:07:07 +02:00
Akihiko Odaki
dde043f6cd Cover WellKnown::HostMetaController more (#3382) 2017-05-29 18:05:30 +02:00
Akihiko Odaki
c778a60e4f Cover Settings::TwoFactorAuthentication::RecoveryCodesController more (#3383) 2017-05-29 18:05:20 +02:00
Akihiko Odaki
c347327d54 Spec Settings::Exports (#3384)
* Spec output of Settings::Exports::BlockedAccountsController

* Spec output of Settings::Exports::FollowingAccountsController

* Spec output of Settings::Exports::MutedAccountsController

* Spec Settings::Exports::BaseController

This commit removes duplicate specs in classes inheriting
Settings::Exports::BaseController as well.
2017-05-29 18:05:01 +02:00
Akihiko Odaki
fd328cf6e8 Cover WellKnown::WebfingerController more (#3385) 2017-05-29 18:04:37 +02:00
Akihiko Odaki
7b473d7514 Cover Settings::TwoFactorAuthentication::ConfirmationsController more (#3386) 2017-05-29 18:04:00 +02:00
Akihiko Odaki
dff576b75d Cover ApplicationHelper more (#3412) 2017-05-29 18:03:37 +02:00
Akihiko Odaki
52ae83d008 Spec Activitystreams2BuilderHelper (#3413) 2017-05-29 18:03:15 +02:00
Akihiko Odaki
5aacd9d4c7 Spec FlashesHelper (#3414) 2017-05-29 18:03:02 +02:00
Akihiko Odaki
d24d3fa283 Spec HomeHelper (#3415) 2017-05-29 18:02:44 +02:00
Akihiko Odaki
c8a226f61c Spec HttpHelper (#3416) 2017-05-29 18:02:32 +02:00
Akihiko Odaki
7a281c477a Cover Admin::PubSubHubHubController more (#3343) 2017-05-29 18:01:37 +02:00
unarist
91c789ec63 Don't stream toots from users who have blocked the recipient user (#3300)
* Don't stream toots from users who have blocked the recipient user

This filter was already applied on the `/api/v1/timelines/public` API, but
not yet for the Streaming API.

* Boosted status' account_id doesn't need for filtering in streaming/index.js

This filtering is only for public/hashtag timelines, but boosts already filtered on FanOutOnWriteService because those timelines don't show boosts.
2017-05-29 18:01:08 +02:00
Daniel Hunsaker
9ead3d1cdb [nanobox] Adjustments for Nanobox development (#3295)
Because Nanobox doesn't run data components in the same container as the code, there are a few tweaks that need to be made in the configuration to get WebPack to work properly in development mode.

The same differences lead to needing to use `DATABASE_URL` by default in the `.env` file for Rails to work correctly.

Limitations of our `.env` loader for Node.js mean the `.env` file needs to be compiled everywhere in order to work, so we compile it in development, now, too. Also, all the `.env.production` tweaks have been consolidated into a single command.

Finally, since Nanobox actually creates the database when it sets up the database server, using the existence of the database alone to determine whether to migrate or setup is insufficient. So we add a condition to `rake db:migrate:setup` to check whether any migrations have run - if the database doesn't exist yet, `db:setup` will be called; if it does, but no migrations have been run, `db:migrate` and `db:seed` are called instead (the same basic idea as what `db:setup` does, but it skips `db:create`, which will only cause problems with an existing DB); otherwise, only `db:migrate` is called.

None of these changes should affect development, and all are designed not to interfere with existing behaviors in other environments.
2017-05-29 17:59:18 +02:00
Atsushi Yamamoto
402c19a924 Add preference setting for delete toot modal (#3368)
* Set delete_modal preference to true by default
* Does not show confirmation modal if delete_modal is false
* Add ja translation for preference setting page
2017-05-29 17:56:13 +02:00
Nolan Lawson
b5e8994844 Prevent wasted render in load_more.js (#3402) 2017-05-29 17:52:45 +02:00
masarakki
4bd327a0c5 fix-rails-minor-version (#3403) 2017-05-29 17:52:26 +02:00
lindwurm
184325077e l10n: Fix Japanese translation (#3410)
* "メデイア" -> "メディア"

Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-05-29 17:52:02 +02:00
Nolan Lawson
8236f942ff Use travis_retry to reduce spurious test failures (#3418) 2017-05-29 17:49:54 +02:00
Eugen Rochko
8963f8c3c2 Bump version to 1.4.1 2017-05-28 19:30:38 +02:00
Nolan Lawson
5e41c26203 Use immutable list in UploadButton to avoid wasteful re-render (#3394) 2017-05-28 19:15:35 +02:00
Clworld
45837c533e Re-add stream end log for WebSocket (#3397) 2017-05-28 19:14:44 +02:00
Eugen Rochko
3fa8512474 Fix video having black border on top due to regression from #2608 (#3392)
The combination of object-fit, relative position 50% from top and translating it
back upwards 50% is what allows us to crop the video properly, so it needs to
be +50%-50%
2017-05-28 19:11:47 +02:00
ster
0e20de9f89 Ukrainian translation: fix typo (#3393) 2017-05-28 19:11:29 +02:00
Nolan Lawson
24d645b7d0 Fix IntersectionObserver isIntersecting in Edge (#3365) 2017-05-28 16:45:42 +02:00
Eugen Rochko
7b23f79d41 Bump version to 1.4.0.6 2017-05-28 16:32:53 +02:00
Eugen Rochko
3b4095cf1b Update bootsnap to 0.3.0 (fix xattr.h error) (#3390) 2017-05-28 16:32:29 +02:00
Nolan Lawson
28cbfb9f10 Simplify isIntersecting in status_list.js (#3371) 2017-05-28 16:26:35 +02:00
Akihiko Odaki
189a06d2a2 Fix Webpack Bundle Analyzer output for Webpacker (#3374)
Webpacker failed to parse output of Webpack when a module requires
non-existent module or has similar errors. This commit fixes the bug.
2017-05-28 16:26:16 +02:00
vidarlee
450441fc11 i18n: Add some tags for Chinese translation (#3379)
* Enhance for the Chinese translation

* Add filtered_languages for Chinese Translation include CN/HK/TW for PR #3175

* i18n: Add some tags for Chinese translation

* i18n: Add some tags for Chinese translation
2017-05-28 16:25:54 +02:00
Masoud Abkenar
b619362a36 Persian translation fixes and updates (#3380)
* Persian translation fix

* Persian translation of new strings
2017-05-28 16:25:45 +02:00
Eugen Rochko
425d02287a Improve streaming API cluster logging (#3370)
* Improve streaming API cluster logging

* Less verbose error middleware logging (stack trace useless there)

* Fix error logging

* Prevent potential issue

* Add missing "done()" in catch of Promise.all, websocket heartbeat re-implemented like in example

* I actually forgot a done(), the absolute madman
2017-05-28 16:25:26 +02:00
Clworld
2e429c0c25 Reject revoked access_token on Streaming API. (#3367) 2017-05-27 23:27:54 +02:00
Eugen Rochko
e0e12b0fee Bump version to 1.4.0.5 2017-05-27 16:56:47 +02:00
Eugen Rochko
62ca37884a Fix #2922 - Load stylesheet from "custom.css" entrypoint when present (#3332)
* Fix #2922 - Load stylesheet from "custom.css" entrypoint when present

This is pretty much the same way it worked as before, albeit with
having to create app/javascript/packs/custom.js with
require('../styles/custom.scss') (or whatever you want really), which
will be a blank slate for you to import whatever you want

* Remove old assets directory

* Extract font-awesome into common.css and always load it
2017-05-27 16:55:09 +02:00
jeroenpraat
f9180823bc Update Dutch strings for 1.4 (#3363)
* Update nl strings for 1.4

* Update nl strings for 1.4

* Update nl strings for 1.4

* nl strings (+1)

More new OTP strings will be translated another time
2017-05-27 16:28:32 +02:00
Quent-in
4b0c667c09 i18n update for Occitan language (#3362)
* Update simple_form.oc.yml

* Added check spam folder

* Update oc.json

abonats => seguidors

* Update oc.yml

* Update oc.json

Added translations + corrections

* Update confirmation_instructions.oc.html.erb

* Update confirmation_instructions.oc.text.erb

* i18n mailer

* Update reset_password_instructions.oc.html.erb
2017-05-27 15:50:40 +02:00
m4sk1n
1b732cad61 i18n: pl: pluralized (#3344)
Signed-off-by: Marcin Mikołajczak <me@m4sk.in>
2017-05-27 13:04:42 +02:00
unarist
ecef03bb15 Fix empty flash message on the settings page (#3345) 2017-05-27 13:04:28 +02:00
happycoloredbanana
9642601126 Avoid comparing domains when looking for an exact match of a local account (#3336) 2017-05-27 00:55:08 +02:00
Eugen Rochko
3836d293a1 Add missing background center on public profile headers (#3340) 2017-05-27 00:54:00 +02:00
Eugen Rochko
0734e1fe33 Language filtering in streaming API (#3339) 2017-05-27 00:53:48 +02:00
Eugen Rochko
44cb08297c Fix some nil errors (#3338)
* Fix nil input not handled well in AuthorExtractor concern

* Fix hard error in ProcessFeedService when replied-to status has been deleted

* Fix nil errors in ProcessInteractionService when favourited status
cannot be found
2017-05-27 00:53:38 +02:00
Eugen Rochko
bd21afb5ed Replace onboarding elephant with friendlier graphic, shorter animation (#3337)
on status fade-in, fix buttons not having pointer cursor
2017-05-27 00:53:25 +02:00
m4sk1n
ef80ad17b3 Updated Polish translation (#3335)
* i18n: updated Polish translation

Signed-off-by: Marcin Mikołajczak <m4sk1n@vivaldi.net>

* i18n: completed Polish translation

Signed-off-by: Marcin Mikołajczak <m4sk1n@vivaldi.net>

* i18n: corrected Polish translation

Signed-off-by: Marcin Mikołajczak <m4sk1n@vivaldi.net>

* i18n: Updated Polish translation

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>

* Update simple_form.pl.yml

* Update simple_form.pl.yml

* updated Polish translation

Signed-off-by: Marcin Mikołajczak <me@m4sk.in>

* Update pl.yml
2017-05-26 19:59:46 +02:00
Eugen Rochko
9ea4f37e78 Add "meta" attribute to return of POST /api/v1/media method as well (#3333) 2017-05-26 18:22:30 +02:00
Eugen Rochko
c48772fd3f Introduce react-textarea-autosize instead of using style.height side effects (#3334) 2017-05-26 18:22:23 +02:00
Akihiko Odaki
860e257a68 Remove redundant call of recent scope in AccountsController (#3330)
recent is included in paginate_by_max_id.
2017-05-26 16:35:25 +02:00
unarist
902d9e34b4 Remove status context construction in the React side (#3331)
because it may causes flicker on the conversation when it contains blocked/muted user's status.

We use `/api/v1/statuses/{id}/context` to obtain status ids in the
conversation which filters blocked/muted user, but also uses internal
cache constructed from `in_reply_to_id` by `normalizeStatus()` in
`reducers/timelines.js` on each status loading which doesn't filter.

So statuses appears in conversation if those are cached, even those
statuses are from blocked/muted user. Then context cache will be updated
with the result of the context API and those statuses will be removed.

I have left the `normalizeStatus()` function itself which is called many
functions in the file as a placeholder for now, but maybe it should be
removed completely.
2017-05-26 16:34:08 +02:00
918 changed files with 25854 additions and 11399 deletions

View File

@@ -14,14 +14,16 @@
],
"plugins": [
"syntax-dynamic-import",
"transform-object-rest-spread",
["transform-object-rest-spread", { "useBuiltIns": true }],
"transform-decorators-legacy",
"transform-class-properties",
[
"react-intl",
{
"messagesDir": "./build/messages"
}
]
],
"preval"
],
"env": {
"development": {
@@ -43,6 +45,7 @@
]
}
],
"transform-react-inline-elements",
[
"transform-runtime",
{

View File

@@ -2,6 +2,7 @@
.env.*
public/system
public/assets
public/packs
node_modules
storybook
neo4j

View File

@@ -11,6 +11,8 @@ DB_NAME=gonano
DB_PASS=$DATA_DB_PASS
DB_PORT=5432
DATABASE_URL=postgresql://$DATA_DB_USER:$DATA_DB_PASS@$DATA_DB_HOST/gonano
# Federation
# Note: Changing LOCAL_DOMAIN or LOCAL_HTTPS at a later time will cause unwanted side effects.
# LOCAL_DOMAIN should *NOT* contain the protocol part of the domain e.g https://example.com.
@@ -67,7 +69,7 @@ SMTP_FROM_ADDRESS=notifications@${APP_NAME}.nanoapp.io
# PAPERCLIP_ROOT_URL=/system
# Optional asset host for multi-server setups
# CDN_HOST=assets.example.com
# CDN_HOST=https://assets.example.com
# S3 (optional)
# S3_ENABLED=true

View File

@@ -31,6 +31,17 @@ PAPERCLIP_SECRET=
SECRET_KEY_BASE=
OTP_SECRET=
# VAPID keys (used for push notifications
# You can generate the keys using the following command (first is the private key, second is the public one)
# You should only generate this once per instance. If you later decide to change it, all push subscription will
# be invalidated, requiring the users to access the website again to resubscribe.
#
# Generate with `rake mastodon:webpush:generate_vapid_key` task (`docker-compose run --rm web rake mastodon:webpush:generate_vapid_key` if you use docker compose)
#
# For more information visit https://rossta.net/blog/using-the-web-push-api-with-vapid.html
VAPID_PRIVATE_KEY=
VAPID_PUBLIC_KEY=
# Registrations
# Single user mode will disable registrations and redirect frontpage to the first profile
# SINGLE_USER_MODE=true
@@ -65,7 +76,7 @@ SMTP_FROM_ADDRESS=notifications@example.com
# PAPERCLIP_ROOT_URL=/system
# Optional asset host for multi-server setups
# CDN_HOST=assets.example.com
# CDN_HOST=https://assets.example.com
# S3 (optional)
# S3_ENABLED=true

View File

@@ -1,7 +1,9 @@
---
root: true
env:
browser: true
node: false
node: true
es6: true
parser: babel-eslint
@@ -21,22 +23,10 @@ parserOptions:
rules:
no-cond-assign: error
no-console: warn
no-irregular-whitespace: error
no-unreachable: error
valid-typeof: error
consistent-return: error
dot-notation: error
eqeqeq: error
no-fallthrough: error
no-unused-expressions: error
strict: off
no-catch-shadow: error
indent:
- warn
- 2
brace-style: warn
comma-dangle:
- error
- always-multiline
comma-spacing:
- warn
- before: false
@@ -44,22 +34,70 @@ rules:
comma-style:
- warn
- last
consistent-return: error
dot-notation: error
eqeqeq: error
indent:
- warn
- 2
jsx-quotes:
- error
- prefer-single
no-catch-shadow: error
no-cond-assign: error
no-console:
- warn
- allow:
- error
no-fallthrough: error
no-irregular-whitespace: error
no-mixed-spaces-and-tabs: warn
no-nested-ternary: warn
no-trailing-spaces: warn
semi: error
no-undef: error
no-unreachable: error
no-unused-expressions: error
no-unused-vars:
- error
- vars: all
args: after-used
ignoreRestSiblings: true
object-curly-spacing:
- error
- always
padded-blocks:
- error
- classes: always
comma-dangle:
quotes:
- error
- always-multiline
- single
semi: error
strict: off
valid-typeof: error
react/jsx-wrap-multilines: error
react/jsx-boolean-value: error
react/jsx-closing-bracket-location:
- error
- line-aligned
react/jsx-curly-spacing: error
react/jsx-equals-spacing: error
react/jsx-first-prop-new-line:
- error
- multiline-multiprop
react/jsx-indent:
- error
- 2
react/jsx-no-bind: error
react/self-closing-comp: error
react/prop-types: error
react/jsx-no-duplicate-props: error
react/jsx-no-undef: error
react/jsx-tag-spacing: error
react/jsx-uses-react: error
react/jsx-uses-vars: error
react/jsx-wrap-multilines: error
react/no-multi-comp: off
react/no-string-refs: error
react/prop-types: error
react/self-closing-comp: error
jsx-a11y/accessible-emoji: warn
jsx-a11y/anchor-has-content: warn

14
.gitattributes vendored Normal file
View File

@@ -0,0 +1,14 @@
* text=auto eol=lf
*.eot -text
*.gif -text
*.gz -text
*.ico -text
*.jpg -text
*.mp3 -text
*.ogg -text
*.png -text
*.ttf -text
*.webm -text
*.woff -text
*.woff2 -text
spec/fixtures/requests/** -text !eol

3
.gitignore vendored
View File

@@ -20,6 +20,8 @@ coverage
public/system
public/assets
public/packs
public/packs-test
public/sw.js
.env
.env.production
node_modules/
@@ -33,6 +35,7 @@ config/deploy/*
# Ignore IDE files
.vscode/
.idea/
# Ignore postgres + redis volume optionally created by docker-compose
postgres

View File

@@ -6,3 +6,4 @@ plugins:
- last 2 versions
- IE >= 11
- iOS >= 9
postcss-object-fit-images: {}

View File

@@ -1,26 +1,35 @@
Rails:
Enabled: true
AllCops:
TargetRubyVersion: 2.3
Exclude:
- 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*'
- 'config/**/*'
- 'bin/*'
- 'Rakefile'
- 'node_modules/**/*'
- 'Vagrantfile'
- 'vendor/**/*'
Style/PerlBackrefs:
AutoCorrect: false
Style/ClassAndModuleChildren:
Bundler/OrderedGems:
Enabled: false
Metrics/BlockNesting:
Max: 2
Layout/AccessModifierIndentation:
EnforcedStyle: indent
Metrics/LineLength:
AllowURI: true
Layout/EmptyLineAfterMagicComment:
Enabled: false
Metrics/MethodLength:
CountComments: false
Max: 10
Layout/SpaceInsideHashLiteralBraces:
EnforcedStyle: space
Metrics/AbcSize:
Max: 100
Metrics/BlockLength:
Exclude:
- 'lib/tasks/**/*'
Metrics/BlockNesting:
Max: 3
@@ -31,22 +40,36 @@ Metrics/ClassLength:
Metrics/CyclomaticComplexity:
Max: 15
Metrics/LineLength:
AllowURI: true
Enabled: false
Metrics/MethodLength:
CountComments: false
Max: 55
Metrics/ModuleLength:
CountComments: false
Max: 200
Metrics/PerceivedComplexity:
Max: 10
Metrics/ParameterLists:
Max: 4
CountKeywordArgs: true
Style/AccessModifierIndentation:
EnforcedStyle: indent
Metrics/PerceivedComplexity:
Max: 10
Rails:
Enabled: true
Rails/HasAndBelongsToMany:
Enabled: false
Rails/SkipsModelValidations:
Enabled: false
Style/ClassAndModuleChildren:
Enabled: false
Style/CollectionMethods:
Enabled: true
@@ -62,36 +85,25 @@ Style/DoubleNegation:
Style/FrozenStringLiteralComment:
Enabled: true
Style/SpaceInsideHashLiteralBraces:
EnforcedStyle: space
Style/TrailingCommaInLiteral:
EnforcedStyleForMultiline: 'comma'
Style/RegexpLiteral:
Style/GuardClause:
Enabled: false
Style/Lambda:
Enabled: false
Style/GuardClause:
Style/PercentLiteralDelimiters:
PreferredDelimiters:
'%i': '()'
'%w': '()'
Style/PerlBackrefs:
AutoCorrect: false
Style/RegexpLiteral:
Enabled: false
Rails/HasAndBelongsToMany:
Style/SymbolArray:
Enabled: false
Bundler/OrderedGems:
Enabled: false
AllCops:
TargetRubyVersion: 2.3
Exclude:
- 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*'
- 'config/**/*'
- 'bin/*'
- 'Rakefile'
- 'node_modules/**/*'
- 'Vagrantfile'
- 'vendor/**/*'
Style/TrailingCommaInLiteral:
EnforcedStyleForMultiline: 'comma'

View File

@@ -4,8 +4,10 @@ cache:
yarn: true
directories:
- node_modules
- public/assets
- public/packs-test
dist: trusty
sudo: false
sudo: required
notifications:
email: false
@@ -30,6 +32,7 @@ addons:
- g++-6
- libprotobuf-dev
- protobuf-compiler
- libicu-dev
rvm:
- 2.3.4
@@ -50,6 +53,6 @@ before_script:
- ln -s /usr/bin/x86_64-linux-gnu-g++-6 "$HOME/g++"
script:
- bundle exec parallel_test spec/ --group-by filesize --type rspec
- travis_retry bundle exec parallel_test spec/ --group-by filesize --type rspec
- npm test
- bundle exec i18n-tasks unused

View File

@@ -3,3 +3,5 @@ libprotobuf-dev
ffmpeg
libxdamage1
libxfixes3
libicu-dev
libidn11-dev

View File

@@ -12,9 +12,12 @@ EXPOSE 3000 4000
WORKDIR /mastodon
RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \
&& echo "@edge https://nl.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& apk -U upgrade \
&& apk add -t build-dependencies \
build-base \
icu-dev \
libidn-dev \
libxml2-dev \
libxslt-dev \
postgresql-dev \
@@ -25,7 +28,9 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
ffmpeg \
file \
git \
icu-libs \
imagemagick@edge \
libidn \
libpq \
libxml2 \
libxslt \
@@ -34,7 +39,7 @@ RUN echo "@edge https://nl.alpinelinux.org/alpine/edge/main" >> /etc/apk/reposit
protobuf \
su-exec \
tini \
&& npm install -g npm@3 && npm install -g yarn \
yarn@edge \
&& update-ca-certificates \
&& rm -rf /tmp/* /var/cache/apk/*

20
Gemfile
View File

@@ -6,7 +6,7 @@ ruby '>= 2.3.0', '< 2.5.0'
gem 'pkg-config', '~> 1.2'
gem 'puma', '~> 3.8'
gem 'rails', '~> 5.0'
gem 'rails', '~> 5.1.0'
gem 'uglifier', '~> 3.2'
gem 'hamlit-rails', '~> 0.2'
@@ -18,26 +18,32 @@ gem 'aws-sdk', '~> 2.9'
gem 'paperclip', '~> 5.1'
gem 'paperclip-av-transcoder', '~> 0.6'
gem 'active_model_serializers', '~> 0.10'
gem 'addressable', '~> 2.5'
gem 'bootsnap'
gem 'browser'
gem 'charlock_holmes', '~> 0.7.3'
gem 'cld3', '~> 3.1'
gem 'devise', '~> 4.2'
gem 'devise-two-factor', '~> 3.0'
gem 'doorkeeper', '~> 4.2'
gem 'fast_blank', '~> 1.0'
gem 'goldfinger', '~> 1.2'
gem 'goldfinger', '~> 2.0'
gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.5'
gem 'htmlentities', '~> 4.3'
gem 'http', '~> 2.2'
gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 0.99'
gem 'idn-ruby', require: 'idn'
gem 'kaminari', '~> 1.0'
gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.1'
gem 'nokogiri', '~> 1.7'
gem 'oj', '~> 3.0'
gem 'ostatus2', '~> 2.0'
gem 'ox', '~> 2.5'
gem 'pundit', '~> 1.1'
gem 'rabl', '~> 0.13'
gem 'rack-attack', '~> 5.0'
gem 'rack-cors', '~> 0.4', require: 'rack/cors'
@@ -45,19 +51,22 @@ gem 'rack-timeout', '~> 0.4'
gem 'rails-i18n', '~> 5.0'
gem 'rails-settings-cached', '~> 0.6'
gem 'redis', '~> 3.3', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 0.10'
gem 'ruby-oembed', '~> 0.12', require: 'oembed'
gem 'sanitize', '~> 4.4'
gem 'sidekiq', '~> 5.0'
gem 'sidekiq-scheduler', '~> 2.1'
gem 'sidekiq-unique-jobs', '~> 5.0'
gem 'sidekiq-bulk', '~>0.1.1'
gem 'simple-navigation', '~> 4.0'
gem 'simple_form', '~> 3.4'
gem 'sprockets-rails', '~> 3.2', require: 'sprockets/railtie'
gem 'statsd-instrument', '~> 2.1'
gem 'twitter-text', '~> 1.14'
gem 'tzinfo-data', '~> 1.2017'
gem 'webpacker', '~> 1.2'
gem 'webpacker', '~> 2.0'
gem 'webpush'
group :development, :test do
gem 'fabrication', '~> 2.16'
@@ -69,8 +78,9 @@ end
group :test do
gem 'capybara', '~> 2.14'
gem 'climate_control', '~> 0.2'
gem 'faker', '~> 1.7'
gem 'microformats2', '~> 3.0'
gem 'microformats', '~> 4.0'
gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.0'
gem 'simplecov', '~> 0.14', require: false
@@ -86,7 +96,7 @@ group :development do
gem 'bullet', '~> 5.5'
gem 'letter_opener', '~> 1.4'
gem 'letter_opener_web', '~> 1.3'
gem 'rubocop', '~> 0.48', require: false
gem 'rubocop', require: false
gem 'brakeman', '~> 3.6', require: false
gem 'bundler-audit', '~> 0.5', require: false
gem 'scss_lint', '~> 0.53', require: false

View File

@@ -1,64 +1,69 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (5.0.3)
actionpack (= 5.0.3)
nio4r (>= 1.2, < 3.0)
actioncable (5.1.2)
actionpack (= 5.1.2)
nio4r (~> 2.0)
websocket-driver (~> 0.6.1)
actionmailer (5.0.3)
actionpack (= 5.0.3)
actionview (= 5.0.3)
activejob (= 5.0.3)
actionmailer (5.1.2)
actionpack (= 5.1.2)
actionview (= 5.1.2)
activejob (= 5.1.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.0.3)
actionview (= 5.0.3)
activesupport (= 5.0.3)
actionpack (5.1.2)
actionview (= 5.1.2)
activesupport (= 5.1.2)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.0.3)
activesupport (= 5.0.3)
actionview (5.1.2)
activesupport (= 5.1.2)
builder (~> 3.1)
erubis (~> 2.7.0)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.10.6)
actionpack (>= 4.1, < 6)
activemodel (>= 4.1, < 6)
case_transform (>= 0.2)
jsonapi-renderer (>= 0.1.1.beta1, < 0.2)
active_record_query_trace (1.5.4)
activejob (5.0.3)
activesupport (= 5.0.3)
activejob (5.1.2)
activesupport (= 5.1.2)
globalid (>= 0.3.6)
activemodel (5.0.3)
activesupport (= 5.0.3)
activerecord (5.0.3)
activemodel (= 5.0.3)
activesupport (= 5.0.3)
arel (~> 7.0)
activesupport (5.0.3)
activemodel (5.1.2)
activesupport (= 5.1.2)
activerecord (5.1.2)
activemodel (= 5.1.2)
activesupport (= 5.1.2)
arel (~> 8.0)
activesupport (5.1.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
airbrussh (1.2.0)
airbrussh (1.3.0)
sshkit (>= 1.6.1, != 1.7.0)
annotate (2.7.1)
annotate (2.7.2)
activerecord (>= 3.2, < 6.0)
rake (>= 10.4, < 12.0)
arel (7.1.4)
rake (>= 10.4, < 13.0)
arel (8.0.0)
ast (2.3.0)
attr_encrypted (3.0.3)
encryptor (~> 3.0.0)
av (0.9.0)
cocaine (~> 0.5.3)
aws-sdk (2.9.21)
aws-sdk-resources (= 2.9.21)
aws-sdk-core (2.9.21)
aws-sdk (2.10.6)
aws-sdk-resources (= 2.10.6)
aws-sdk-core (2.10.6)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
aws-sdk-resources (2.9.21)
aws-sdk-core (= 2.9.21)
aws-sdk-resources (2.10.6)
aws-sdk-core (= 2.10.6)
aws-sigv4 (1.0.0)
bcrypt (3.1.11)
better_errors (2.1.1)
@@ -67,9 +72,10 @@ GEM
rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootsnap (0.2.14)
bootsnap (1.1.1)
msgpack (~> 1.0)
brakeman (3.6.1)
brakeman (3.6.2)
browser (2.4.0)
builder (3.2.3)
bullet (5.5.1)
activesupport (>= 3.0.0)
@@ -77,7 +83,7 @@ GEM
bundler-audit (0.5.0)
bundler (~> 1.2)
thor (~> 0.18)
capistrano (3.8.1)
capistrano (3.8.2)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
@@ -85,7 +91,7 @@ GEM
capistrano-bundler (1.2.0)
capistrano (~> 3.1)
sshkit (~> 1.2)
capistrano-rails (1.2.3)
capistrano-rails (1.3.0)
capistrano (~> 3.1)
capistrano-bundler (~> 1.1)
capistrano-rbenv (2.1.1)
@@ -93,15 +99,18 @@ GEM
sshkit (~> 1.3)
capistrano-yarn (2.0.2)
capistrano (~> 3.0)
capybara (2.14.0)
capybara (2.14.4)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
case_transform (0.2)
activesupport
charlock_holmes (0.7.3)
chunky_png (1.3.8)
cld3 (3.1.2)
cld3 (3.1.3)
ffi (>= 1.1.0, < 1.10.0)
climate_control (0.2.0)
cocaine (0.5.8)
@@ -130,7 +139,7 @@ GEM
docile (1.1.5)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (4.2.5)
doorkeeper (4.2.6)
railties (>= 4.2)
dotenv (2.2.1)
dotenv-rails (2.2.1)
@@ -141,8 +150,9 @@ GEM
thread
thread_safe
encryptor (3.0.0)
erubi (1.6.1)
erubis (2.7.0)
et-orbi (1.0.4)
et-orbi (1.0.5)
tzinfo
execjs (2.7.0)
fabrication (2.16.1)
@@ -155,11 +165,12 @@ GEM
ruby-progressbar (~> 1.4)
globalid (0.4.0)
activesupport (>= 4.2.0)
goldfinger (1.2.0)
addressable (~> 2.4)
http (~> 2.0)
nokogiri (~> 1.6)
hamlit (2.8.1)
goldfinger (2.0.0)
addressable (~> 2.5)
http (~> 2.2)
nokogiri (~> 1.8)
oj (~> 3.0)
hamlit (2.8.4)
temple (>= 0.8.0)
thor
tilt
@@ -171,6 +182,7 @@ GEM
hashdiff (0.3.4)
highline (1.7.8)
hiredis (0.6.1)
hkdf (0.3.0)
htmlentities (4.3.4)
http (2.2.2)
addressable (~> 2.3)
@@ -180,12 +192,12 @@ GEM
http-cookie (1.0.3)
domain_name (~> 0.5)
http-form_data (1.0.3)
http_accept_language (2.1.0)
http_accept_language (2.1.1)
http_parser.rb (0.6.0)
httplog (0.99.3)
httplog (0.99.4)
colorize
rack
i18n (0.8.1)
i18n (0.8.4)
i18n-tasks (0.9.15)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
@@ -196,8 +208,11 @@ GEM
parser (>= 2.2.3.0)
rainbow (~> 2.2)
terminal-table (>= 1.5.1)
idn-ruby (0.1.0)
jmespath (1.3.1)
json (2.1.0)
jsonapi-renderer (0.1.2)
jwt (1.5.6)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
@@ -225,32 +240,34 @@ GEM
railties (>= 4, < 5.2)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.5)
mail (2.6.6)
mime-types (>= 1.16, < 4)
mario-redis-lock (1.2.0)
redis (~> 3, >= 3.0.5)
method_source (0.8.2)
microformats2 (3.1.0)
microformats (4.0.7)
json
nokogiri
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
mini_portile2 (2.1.0)
mini_portile2 (2.2.0)
minitest (5.10.2)
msgpack (1.1.0)
multi_json (1.12.1)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (4.1.0)
nio4r (2.0.0)
nokogiri (1.7.2)
mini_portile2 (~> 2.1.0)
nokogumbo (1.4.11)
nio4r (2.1.0)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.0)
nokogumbo (1.4.13)
nokogiri
oj (3.0.9)
openssl (2.0.3)
oj (3.2.0)
openssl (2.0.4)
orm_adapter (0.5.0)
ostatus2 (2.0.0)
ostatus2 (2.0.1)
addressable (~> 2.4)
http (~> 2.0)
nokogiri (~> 1.6)
@@ -270,10 +287,10 @@ GEM
parallel
parser (2.4.0.0)
ast (~> 2.2)
pg (0.20.0)
pg (0.21.0)
pghero (1.7.0)
activerecord
pkg-config (1.2.0)
pkg-config (1.2.3)
powerpack (0.1.1)
pry (0.10.4)
coderay (~> 1.1.0)
@@ -282,7 +299,9 @@ GEM
pry-rails (0.3.6)
pry (>= 0.10.4)
public_suffix (2.0.5)
puma (3.8.2)
puma (3.9.1)
pundit (1.1.0)
activesupport (>= 3.0.0)
rabl (0.13.1)
activesupport (>= 2.3.14)
rack (2.0.3)
@@ -294,17 +313,17 @@ GEM
rack-test (0.6.3)
rack (>= 1.0)
rack-timeout (0.4.2)
rails (5.0.3)
actioncable (= 5.0.3)
actionmailer (= 5.0.3)
actionpack (= 5.0.3)
actionview (= 5.0.3)
activejob (= 5.0.3)
activemodel (= 5.0.3)
activerecord (= 5.0.3)
activesupport (= 5.0.3)
rails (5.1.2)
actioncable (= 5.1.2)
actionmailer (= 5.1.2)
actionpack (= 5.1.2)
actionview (= 5.1.2)
activejob (= 5.1.2)
activemodel (= 5.1.2)
activerecord (= 5.1.2)
activesupport (= 5.1.2)
bundler (>= 1.3.0, < 2.0)
railties (= 5.0.3)
railties (= 5.1.2)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1)
@@ -320,15 +339,15 @@ GEM
railties (~> 5.0)
rails-settings-cached (0.6.5)
rails (>= 4.2.0)
railties (5.0.3)
actionpack (= 5.0.3)
activesupport (= 5.0.3)
railties (5.1.2)
actionpack (= 5.1.2)
activesupport (= 5.1.2)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.2.2)
rake
rake (11.3.0)
rake (12.0.0)
redis (3.3.3)
redis-actionpack (5.0.1)
actionpack (>= 4.0, < 6)
@@ -370,11 +389,12 @@ GEM
rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.6.0)
rspec-support (~> 3.6.0)
rspec-sidekiq (3.0.1)
rspec-sidekiq (3.0.3)
rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0)
rspec-support (3.6.0)
rubocop (0.48.1)
rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
@@ -382,23 +402,26 @@ GEM
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-oembed (0.12.0)
ruby-progressbar (1.8.1)
rufus-scheduler (3.4.0)
rufus-scheduler (3.4.2)
et-orbi (~> 1.0)
safe_yaml (1.0.4)
sanitize (4.4.0)
sanitize (4.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (~> 1.4.1)
sass (3.4.24)
scss_lint (0.53.0)
scss_lint (0.54.0)
rake (>= 0.9, < 13)
sass (~> 3.4.20)
sidekiq (5.0.0)
sidekiq (5.0.3)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (>= 1.5.0)
redis (~> 3.3, >= 3.3.3)
sidekiq-scheduler (2.1.4)
sidekiq-bulk (0.1.1)
activesupport
sidekiq
sidekiq-scheduler (2.1.7)
redis (~> 3)
rufus-scheduler (~> 3.2)
sidekiq (>= 3)
@@ -435,7 +458,7 @@ GEM
thread (0.2.2)
thread_safe (0.3.6)
tilt (2.0.7)
twitter-text (1.14.5)
twitter-text (1.14.6)
unf (~> 0.1.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
@@ -446,7 +469,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.4)
unicode-display_width (1.2.1)
unicode-display_width (1.3.0)
uniform_notifier (1.10.0)
warden (1.2.7)
rack (>= 1.0)
@@ -454,20 +477,24 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
webpacker (1.2)
webpacker (2.0)
activesupport (>= 4.2)
multi_json (~> 1.2)
railties (>= 4.2)
webpush (0.3.2)
hkdf (~> 0.2)
jwt
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
xpath (2.0.0)
xpath (2.1.0)
nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
active_model_serializers (~> 0.10)
active_record_query_trace (~> 1.5)
addressable (~> 2.5)
annotate (~> 2.7)
@@ -476,6 +503,7 @@ DEPENDENCIES
binding_of_caller (~> 0.7)
bootsnap
brakeman (~> 3.6)
browser
bullet (~> 5.5)
bundler-audit (~> 0.5)
capistrano (~> 3.8)
@@ -483,7 +511,9 @@ DEPENDENCIES
capistrano-rbenv (~> 2.1)
capistrano-yarn (~> 2.0)
capybara (~> 2.14)
charlock_holmes (~> 0.7.3)
cld3 (~> 3.1)
climate_control (~> 0.2)
devise (~> 4.2)
devise-two-factor (~> 3.0)
doorkeeper (~> 4.2)
@@ -492,7 +522,7 @@ DEPENDENCIES
faker (~> 1.7)
fast_blank (~> 1.0)
fuubar (~> 2.2)
goldfinger (~> 1.2)
goldfinger (~> 2.0)
hamlit-rails (~> 0.2)
hiredis (~> 0.6)
htmlentities (~> 4.3)
@@ -500,12 +530,15 @@ DEPENDENCIES
http_accept_language (~> 2.1)
httplog (~> 0.99)
i18n-tasks (~> 0.9)
idn-ruby
kaminari (~> 1.0)
letter_opener (~> 1.4)
letter_opener_web (~> 1.3)
link_header (~> 0.0)
lograge (~> 0.5)
microformats2 (~> 3.0)
mario-redis-lock (~> 1.2)
microformats (~> 4.0)
mime-types (~> 3.1)
nokogiri (~> 1.7)
oj (~> 3.0)
ostatus2 (~> 2.0)
@@ -518,11 +551,12 @@ DEPENDENCIES
pkg-config (~> 1.2)
pry-rails (~> 0.3)
puma (~> 3.8)
pundit (~> 1.1)
rabl (~> 0.13)
rack-attack (~> 5.0)
rack-cors (~> 0.4)
rack-timeout (~> 0.4)
rails (~> 5.0)
rails (~> 5.1.0)
rails-controller-testing (~> 1.0)
rails-i18n (~> 5.0)
rails-settings-cached (~> 0.6)
@@ -532,11 +566,12 @@ DEPENDENCIES
rqrcode (~> 0.10)
rspec-rails (~> 3.6)
rspec-sidekiq (~> 3.0)
rubocop (~> 0.48)
rubocop
ruby-oembed (~> 0.12)
sanitize (~> 4.4)
scss_lint (~> 0.53)
sidekiq (~> 5.0)
sidekiq-bulk (~> 0.1.1)
sidekiq-scheduler (~> 2.1)
sidekiq-unique-jobs (~> 5.0)
simple-navigation (~> 4.0)
@@ -548,10 +583,11 @@ DEPENDENCIES
tzinfo-data (~> 1.2017)
uglifier (~> 3.2)
webmock (~> 3.0)
webpacker (~> 1.2)
webpacker (~> 2.0)
webpush
RUBY VERSION
ruby 2.4.1p111
BUNDLED WITH
1.14.6
1.15.2

View File

@@ -1,4 +1,4 @@
Mastodon
![Mastodon](https://i.imgur.com/NhZc40l.png)
========
[![Build Status](http://img.shields.io/travis/tootsuite/mastodon.svg)][travis]
@@ -13,7 +13,7 @@ An alternative implementation of the GNU social project. Based on [ActivityStrea
Click on the screenshot to watch a demo of the UI:
[![Screenshot](http://puu.sh/vMcvm/290f459dd4.jpg)][youtube_demo]
[![Screenshot](https://i.imgur.com/pG3Nnz3.jpg)][youtube_demo]
[youtube_demo]: https://www.youtube.com/watch?v=YO1jQ8_rAMU

7
Vagrantfile vendored
View File

@@ -35,6 +35,8 @@ sudo apt-get install \
postgresql-contrib \
protobuf-compiler \
yarn \
libicu-dev \
libidn11-dev \
libprotobuf-dev \
libreadline-dev \
-y
@@ -42,9 +44,12 @@ sudo apt-get install \
# Install rvm
read RUBY_VERSION < .ruby-version
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -sSL https://get.rvm.io | bash -s stable --ruby=$RUBY_VERSION
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
source /home/vagrant/.rvm/scripts/rvm
# Install Ruby
rvm install ruby-$RUBY_VERSION
# Configure database
sudo -u postgres createuser -U postgres vagrant -s
sudo -u postgres createdb -U postgres mastodon_development

View File

@@ -2,7 +2,7 @@
"name": "Mastodon",
"description": "A GNU Social-compatible microblogging server",
"repository": "https://github.com/tootsuite/mastodon",
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/assets/images/logo.png",
"logo": "https://github.com/tootsuite/mastodon/raw/master/app/javascript/images/logo.svg",
"env": {
"HEROKU": {
"description": "Leave this as true",

View File

@@ -2,9 +2,12 @@
class AboutController < ApplicationController
before_action :set_body_classes
before_action :set_instance_presenter, only: [:show, :more]
before_action :set_instance_presenter, only: [:show, :more, :terms]
def show; end
def show
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
@initial_state_json = serializable_resource.to_json
end
def more; end
@@ -15,6 +18,7 @@ class AboutController < ApplicationController
def new_user
User.new.tap(&:build_account)
end
helper_method :new_user
def set_instance_presenter
@@ -24,4 +28,11 @@ class AboutController < ApplicationController
def set_body_classes
@body_classes = 'about-body'
end
def initial_state_params
{
settings: {},
token: current_session&.token,
}
end
end

View File

@@ -2,20 +2,23 @@
class AccountsController < ApplicationController
include AccountControllerConcern
include SignatureVerification
def show
respond_to do |format|
format.html do
@statuses = @account.statuses.permitted_for(@account, current_account).recent.paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses, Status)
end
format.atom do
@entries = @account.stream_entries.recent.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
render xml: AtomSerializer.render(AtomSerializer.new.feed(@account, @entries.to_a))
@entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(20, params[:max_id], params[:since_id])
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.to_a))
end
format.activitystreams2
format.json do
render json: @account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter
end
end
end

View File

@@ -0,0 +1,27 @@
# frozen_string_literal: true
class ActivityPub::OutboxesController < Api::BaseController
before_action :set_account
def show
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(20, params[:max_id], params[:since_id])
@statuses = cache_collection(@statuses, Status)
render json: outbox_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
end
private
def set_account
@account = Account.find_local!(params[:account_username])
end
def outbox_presenter
ActivityPub::CollectionPresenter.new(
id: account_outbox_url(@account),
type: :ordered,
size: @account.statuses_count,
items: @statuses
)
end
end

View File

@@ -2,16 +2,43 @@
module Admin
class AccountsController < BaseController
before_action :set_account, only: [:show, :subscribe, :unsubscribe, :redownload]
before_action :require_remote_account!, only: [:subscribe, :unsubscribe, :redownload]
def index
@accounts = filtered_accounts.page(params[:page])
end
def show
@account = Account.find(params[:id])
def show; end
def subscribe
Pubsubhubbub::SubscribeWorker.perform_async(@account.id)
redirect_to admin_account_path(@account.id)
end
def unsubscribe
UnsubscribeService.new.call(@account)
redirect_to admin_account_path(@account.id)
end
def redownload
@account.reset_avatar!
@account.reset_header!
@account.save!
redirect_to admin_account_path(@account.id)
end
private
def set_account
@account = Account.find(params[:id])
end
def require_remote_account!
redirect_to admin_account_path(@account.id) if @account.local?
end
def filtered_accounts
AccountFilter.new(filter_params).results
end

View File

@@ -3,13 +3,29 @@
module Admin
class InstancesController < BaseController
def index
@instances = ordered_instances.page(params[:page])
@instances = ordered_instances
end
def resubscribe
params.require(:by_domain)
Pubsubhubbub::SubscribeWorker.push_bulk(subscribeable_accounts.pluck(:id))
redirect_to admin_instances_path
end
private
def paginated_instances
Account.remote.by_domain_accounts.page(params[:page])
end
helper_method :paginated_instances
def ordered_instances
Account.remote.by_domain_accounts
paginated_instances.map { |account| Instance.new(account) }
end
def subscribeable_accounts
Account.with_followers.remote.where(domain: params[:by_domain])
end
end
end

View File

@@ -1,9 +0,0 @@
# frozen_string_literal: true
module Admin
class PubsubhubbubController < BaseController
def index
@subscriptions = Subscription.order(id: :desc).includes(:account).page(params[:page])
end
end
end

View File

@@ -2,8 +2,17 @@
module Admin
class ReportedStatusesController < BaseController
include Authorization
before_action :set_report
before_action :set_status
before_action :set_status, only: [:update, :destroy]
def create
@form = Form::StatusBatch.new(form_status_batch_params)
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
redirect_to admin_report_path(@report)
end
def update
@status.update(status_params)
@@ -11,8 +20,9 @@ module Admin
end
def destroy
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
redirect_to admin_report_path(@report)
render json: @status
end
private
@@ -21,6 +31,10 @@ module Admin
params.require(:status).permit(:sensitive)
end
def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end
def set_report
@report = Report.find(params[:report_id])
end

View File

@@ -8,7 +8,9 @@ module Admin
@reports = filtered_reports.page(params[:page])
end
def show; end
def show
@form = Form::StatusBatch.new
end
def update
process_report

View File

@@ -8,13 +8,21 @@ module Admin
site_title
site_description
site_extended_description
site_terms
open_registrations
closed_registrations_message
open_deletion
timeline_preview
).freeze
BOOLEAN_SETTINGS = %w(
open_registrations
open_deletion
timeline_preview
).freeze
BOOLEAN_SETTINGS = %w(open_registrations).freeze
def edit
@settings = Setting.all_as_records
@admin_settings = Form::AdminSettings.new
end
def update
@@ -23,19 +31,19 @@ module Admin
setting.update(value: value_for_update(key, value))
end
flash[:notice] = 'Success!'
flash[:notice] = I18n.t('generic.changes_saved_msg')
redirect_to edit_admin_settings_path
end
private
def settings_params
params.permit(ADMIN_SETTINGS)
params.require(:form_admin_settings).permit(ADMIN_SETTINGS)
end
def value_for_update(key, value)
if BOOLEAN_SETTINGS.include?(key)
value == 'true'
value == '1'
else
value
end

View File

@@ -0,0 +1,69 @@
# frozen_string_literal: true
module Admin
class StatusesController < BaseController
include Authorization
helper_method :current_params
before_action :set_account
before_action :set_status, only: [:update, :destroy]
PAR_PAGE = 20
def index
@statuses = @account.statuses
if params[:media]
account_media_status_ids = @account.media_attachments.attached.reorder(nil).select(:status_id).distinct
@statuses.merge!(Status.where(id: account_media_status_ids))
end
@statuses = @statuses.preload(:media_attachments, :mentions).page(params[:page]).per(PAR_PAGE)
@form = Form::StatusBatch.new
end
def create
@form = Form::StatusBatch.new(form_status_batch_params)
flash[:alert] = t('admin.statuses.failed_to_execute') unless @form.save
redirect_to admin_account_statuses_path(@account.id, current_params)
end
def update
@status.update(status_params)
redirect_to admin_account_statuses_path(@account.id, current_params)
end
def destroy
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
render json: @status
end
private
def status_params
params.require(:status).permit(:sensitive)
end
def form_status_batch_params
params.require(:form_status_batch).permit(:action, status_ids: [])
end
def set_status
@status = @account.statuses.find(params[:id])
end
def set_account
@account = Account.find(params[:account_id])
end
def current_params
page = (params[:page] || 1).to_i
{
media: params[:media],
page: page > 1 && page,
}.select { |_, value| value.present? }
end
end
end

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
module Admin
class SubscriptionsController < BaseController
def index
@subscriptions = ordered_subscriptions.page(requested_page)
end
private
def ordered_subscriptions
Subscription.order(id: :desc).includes(:account)
end
def requested_page
params[:page].to_i
end
end
end

View File

@@ -1,25 +0,0 @@
# frozen_string_literal: true
class Api::Activitypub::ActivitiesController < ApiController
# before_action :set_follow, only: [:show_follow]
before_action :set_status, only: [:show_status]
respond_to :activitystreams2
# Show a status in AS2 format, as either an Announce (reblog) or a Create (post) activity.
def show_status
return forbidden unless @status.permitted?
if @status.reblog?
render :show_status_announce
else
render :show_status_create
end
end
private
def set_status
@status = Status.find(params[:id])
end
end

View File

@@ -1,17 +0,0 @@
# frozen_string_literal: true
class Api::Activitypub::NotesController < ApiController
before_action :set_status
respond_to :activitystreams2
def show
forbidden unless @status.permitted?
end
private
def set_status
@status = Status.find(params[:id])
end
end

View File

@@ -1,69 +0,0 @@
# frozen_string_literal: true
class Api::Activitypub::OutboxController < ApiController
before_action :set_account
respond_to :activitystreams2
def show
if params[:max_id] || params[:since_id]
show_outbox_page
else
show_base_outbox
end
end
private
def show_base_outbox
@statuses = Status.as_outbox_timeline(@account)
@statuses = cache_collection(@statuses)
set_maps(@statuses)
set_first_last_page(@statuses)
render :show
end
def show_outbox_page
all_statuses = Status.as_outbox_timeline(@account)
@statuses = all_statuses.paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
all_statuses = cache_collection(all_statuses)
@statuses = cache_collection(@statuses)
set_maps(@statuses)
set_first_last_page(all_statuses)
@next_page_url = api_activitypub_outbox_url(pagination_params(max_id: @statuses.last.id)) unless @statuses.empty?
@prev_page_url = api_activitypub_outbox_url(pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
@paginated = @next_page_url || @prev_page_url
@part_of_url = api_activitypub_outbox_url
set_pagination_headers(@next_page_url, @prev_page_url)
render :show_page
end
def cache_collection(raw)
super(raw, Status)
end
def set_account
@account = Account.find(params[:id])
end
def set_first_last_page(statuses) # rubocop:disable Style/AccessorMethodName
return if statuses.empty?
@first_page_url = api_activitypub_outbox_url(max_id: statuses.first.id + 1)
@last_page_url = api_activitypub_outbox_url(since_id: statuses.last.id - 1)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
end

View File

@@ -1,16 +1,14 @@
# frozen_string_literal: true
class ApiController < ApplicationController
class Api::BaseController < ApplicationController
DEFAULT_STATUSES_LIMIT = 20
DEFAULT_ACCOUNTS_LIMIT = 40
protect_from_forgery with: :null_session
include RateLimitHeaders
skip_before_action :verify_authenticity_token
skip_before_action :store_current_location
before_action :set_rate_limit_headers
rescue_from ActiveRecord::RecordInvalid, Mastodon::ValidationError do |e|
render json: { error: e.to_s }, status: 422
end
@@ -19,11 +17,7 @@ class ApiController < ApplicationController
render json: { error: 'Record not found' }, status: 404
end
rescue_from Goldfinger::Error do
render json: { error: 'Remote account could not be resolved' }, status: 422
end
rescue_from HTTP::Error do
rescue_from HTTP::Error, Mastodon::UnexpectedResponseError do
render json: { error: 'Remote data could not be fetched' }, status: 503
end
@@ -45,17 +39,6 @@ class ApiController < ApplicationController
protected
def set_rate_limit_headers
return if request.env['rack.attack.throttle_data'].nil?
now = Time.now.utc
match_data = request.env['rack.attack.throttle_data']['api']
response.headers['X-RateLimit-Limit'] = match_data[:limit].to_s
response.headers['X-RateLimit-Remaining'] = (match_data[:limit] - match_data[:count]).to_s
response.headers['X-RateLimit-Reset'] = (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6)
end
def set_pagination_headers(next_path = nil, prev_path = nil)
links = []
links << [next_path, [%w(rel next)]] if next_path

View File

@@ -1,33 +1,24 @@
# frozen_string_literal: true
class Api::OEmbedController < ApiController
class Api::OEmbedController < Api::BaseController
respond_to :json
def show
@stream_entry = stream_entry_from_url(params[:url])
@width = params[:maxwidth].present? ? params[:maxwidth].to_i : 400
@height = params[:maxheight].present? ? params[:maxheight].to_i : nil
@stream_entry = find_stream_entry.stream_entry
render json: @stream_entry, serializer: OEmbedSerializer, width: maxwidth_or_default, height: maxheight_or_default
end
private
def stream_entry_from_url(url)
params = Rails.application.routes.recognize_path(url)
raise ActiveRecord::RecordNotFound unless recognized_stream_entry_url?(params)
stream_entry(params)
def find_stream_entry
StreamEntryFinder.new(params[:url])
end
def recognized_stream_entry_url?(params)
%w(stream_entries statuses).include?(params[:controller]) && params[:action] == 'show'
def maxwidth_or_default
(params[:maxwidth].presence || 400).to_i
end
def stream_entry(params)
if params[:controller] == 'stream_entries'
StreamEntry.find(params[:id])
else
Status.find(params[:id]).stream_entry
end
def maxheight_or_default
params[:maxheight].present? ? params[:maxheight].to_i : nil
end
end

View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Api::PushController < ApiController
class Api::PushController < Api::BaseController
include SignatureVerification
def update
response, status = process_push_request
render plain: response, status: status
@@ -11,7 +13,7 @@ class Api::PushController < ApiController
def process_push_request
case hub_mode
when 'subscribe'
Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds)
Pubsubhubbub::SubscribeService.new.call(account_from_topic, hub_callback, hub_secret, hub_lease_seconds, verified_domain)
when 'unsubscribe'
Pubsubhubbub::UnsubscribeService.new.call(account_from_topic, hub_callback)
else
@@ -57,6 +59,10 @@ class Api::PushController < ApiController
TagManager.instance.web_domain?(hub_topic_domain)
end
def verified_domain
return signed_request_account.domain if signed_request_account
end
def hub_topic_domain
hub_topic_uri.host + (hub_topic_uri.port ? ":#{hub_topic_uri.port}" : '')
end

View File

@@ -1,14 +1,12 @@
# frozen_string_literal: true
class Api::SalmonController < ApiController
class Api::SalmonController < Api::BaseController
before_action :set_account
respond_to :txt
def update
payload = request.body.read
if !payload.nil? && verify?(payload)
SalmonWorker.perform_async(@account.id, payload.force_encoding('UTF-8'))
if verify_payload?
process_salmon
head 201
else
head 202
@@ -21,7 +19,15 @@ class Api::SalmonController < ApiController
@account = Account.find(params[:id])
end
def verify?(payload)
VerifySalmonService.new.call(payload)
def payload
@_payload ||= request.body.read
end
def verify_payload?
payload.present? && VerifySalmonService.new.call(payload)
end
def process_salmon
SalmonWorker.perform_async(@account.id, payload.force_encoding('UTF-8'))
end
end

View File

@@ -1,22 +1,19 @@
# frozen_string_literal: true
class Api::SubscriptionsController < ApiController
class Api::SubscriptionsController < Api::BaseController
before_action :set_account
respond_to :txt
def show
if @account.subscription(api_subscription_url(@account.id)).valid?(params['hub.topic'])
@account.update(subscription_expires_at: Time.now.utc + (params['hub.lease_seconds'] || 86_400).to_i.seconds)
render plain: HTMLEntities.new.encode(params['hub.challenge']), status: 200
if subscription.valid?(params['hub.topic'])
@account.update(subscription_expires_at: future_expires)
render plain: encoded_challenge, status: 200
else
head 404
end
end
def update
body = request.body.read
subscription = @account.subscription(api_subscription_url(@account.id))
if subscription.verify(body, request.headers['HTTP_X_HUB_SIGNATURE'])
ProcessingWorker.perform_async(@account.id, body.force_encoding('UTF-8'))
end
@@ -26,6 +23,28 @@ class Api::SubscriptionsController < ApiController
private
def subscription
@_subscription ||= @account.subscription(
api_subscription_url(@account.id)
)
end
def body
@_body ||= request.body.read
end
def encoded_challenge
HTMLEntities.new.encode(params['hub.challenge'])
end
def future_expires
Time.now.utc + lease_seconds_or_default
end
def lease_seconds_or_default
(params['hub.lease_seconds'] || 1.day).to_i.seconds
end
def set_account
@account = Account.find(params[:id])
end

View File

@@ -0,0 +1,23 @@
# frozen_string_literal: true
class Api::V1::Accounts::CredentialsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write }, only: [:update]
before_action :require_user!
def show
@account = current_account
render json: @account, serializer: REST::CredentialAccountSerializer
end
def update
current_account.update!(account_params)
@account = current_account
render json: @account, serializer: REST::CredentialAccountSerializer
end
private
def account_params
params.permit(:display_name, :note, :avatar, :header)
end
end

View File

@@ -0,0 +1,68 @@
# frozen_string_literal: true
class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :set_account
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def set_account
@account = Account.find(params[:account_id])
end
def load_accounts
default_accounts.merge(paginated_follows).to_a
end
def default_accounts
Account.includes(:active_relationships).references(:active_relationships)
end
def paginated_follows
Follow.where(target_account: @account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_account_followers_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_account_followers_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.active_relationships.first.id
end
def pagination_since_id
@accounts.first.active_relationships.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
end

View File

@@ -0,0 +1,68 @@
# frozen_string_literal: true
class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :set_account
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def set_account
@account = Account.find(params[:account_id])
end
def load_accounts
default_accounts.merge(paginated_follows).to_a
end
def default_accounts
Account.includes(:passive_relationships).references(:passive_relationships)
end
def paginated_follows
Follow.where(account: @account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_account_following_index_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_account_following_index_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.passive_relationships.first.id
end
def pagination_since_id
@accounts.first.passive_relationships.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
end

View File

@@ -0,0 +1,23 @@
# frozen_string_literal: true
class Api::V1::Accounts::RelationshipsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
respond_to :json
def index
@accounts = Account.where(id: account_ids).select('id')
render json: @accounts, each_serializer: REST::RelationshipSerializer, relationships: relationships
end
private
def relationships
AccountRelationshipsPresenter.new(@accounts, current_user.account_id)
end
def account_ids
@_account_ids ||= Array(params[:id]).map(&:to_i)
end
end

View File

@@ -0,0 +1,28 @@
# frozen_string_literal: true
class Api::V1::Accounts::SearchController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
respond_to :json
def show
@accounts = account_search
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def account_search
AccountSearchService.new.call(
params[:q],
limit_param(DEFAULT_ACCOUNTS_LIMIT),
resolving_search?,
current_account
)
end
def resolving_search?
params[:resolve] == 'true'
end
end

View File

@@ -0,0 +1,91 @@
# frozen_string_literal: true
class Api::V1::Accounts::StatusesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :set_account
after_action :insert_pagination_headers
respond_to :json
def index
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
private
def set_account
@account = Account.find(params[:account_id])
end
def load_statuses
cached_account_statuses
end
def cached_account_statuses
cache_collection account_statuses, Status
end
def account_statuses
default_statuses.tap do |statuses|
statuses.merge!(only_media_scope) if params[:only_media]
statuses.merge!(no_replies_scope) if params[:exclude_replies]
end
end
def default_statuses
permitted_account_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def permitted_account_statuses
@account.statuses.permitted_for(@account, current_account)
end
def only_media_scope
Status.where(id: account_media_status_ids)
end
def account_media_status_ids
@account.media_attachments.attached.reorder(nil).select(:status_id).distinct
end
def no_replies_scope
Status.without_replies
end
def pagination_params(core_params)
params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_account_statuses_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @statuses.empty?
api_v1_account_statuses_url pagination_params(since_id: pagination_since_id)
end
end
def records_continue?
@statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -1,132 +1,45 @@
# frozen_string_literal: true
class Api::V1::AccountsController < ApiController
before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute, :update_credentials]
class Api::V1::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, except: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
before_action -> { doorkeeper_authorize! :follow }, only: [:follow, :unfollow, :block, :unblock, :mute, :unmute]
before_action -> { doorkeeper_authorize! :write }, only: [:update_credentials]
before_action :require_user!, except: [:show, :following, :followers, :statuses]
before_action :set_account, except: [:verify_credentials, :update_credentials, :suggestions, :search]
before_action :require_user!, except: [:show]
before_action :set_account
respond_to :json
def show; end
def verify_credentials
@account = current_user.account
render :show
end
def update_credentials
current_account.update!(account_params)
@account = current_account
render :show
end
def following
@accounts = Account.includes(:passive_relationships)
.references(:passive_relationships)
.merge(Follow.where(account: @account)
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
.to_a
next_path = following_api_v1_account_url(pagination_params(max_id: @accounts.last.passive_relationships.first.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = following_api_v1_account_url(pagination_params(since_id: @accounts.first.passive_relationships.first.id)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
render :index
end
def followers
@accounts = Account.includes(:active_relationships)
.references(:active_relationships)
.merge(Follow.where(target_account: @account)
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]))
.to_a
next_path = followers_api_v1_account_url(pagination_params(max_id: @accounts.last.active_relationships.first.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = followers_api_v1_account_url(pagination_params(since_id: @accounts.first.active_relationships.first.id)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
render :index
end
def statuses
@statuses = @account.statuses.permitted_for(@account, current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
@statuses = @statuses.where(id: MediaAttachment.where(account: @account).where.not(status_id: nil).reorder('').select('distinct status_id')) if params[:only_media]
@statuses = @statuses.without_replies if params[:exclude_replies]
@statuses = cache_collection(@statuses, Status)
set_maps(@statuses)
next_path = statuses_api_v1_account_url(statuses_pagination_params(max_id: @statuses.last.id)) if @statuses.size == limit_param(DEFAULT_STATUSES_LIMIT)
prev_path = statuses_api_v1_account_url(statuses_pagination_params(since_id: @statuses.first.id)) unless @statuses.empty?
set_pagination_headers(next_path, prev_path)
def show
render json: @account, serializer: REST::AccountSerializer
end
def follow
FollowService.new.call(current_user.account, @account.acct)
set_relationship
render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
def block
BlockService.new.call(current_user.account, @account)
@following = { @account.id => false }
@followed_by = { @account.id => false }
@blocking = { @account.id => true }
@requested = { @account.id => false }
@muting = { @account.id => current_account.muting?(@account.id) }
@domain_blocking = { @account.id => current_account.domain_blocking?(@account.domain) }
render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
def mute
MuteService.new.call(current_user.account, @account)
set_relationship
render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
def unfollow
UnfollowService.new.call(current_user.account, @account)
set_relationship
render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
def unblock
UnblockService.new.call(current_user.account, @account)
set_relationship
render :relationship
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
def unmute
UnmuteService.new.call(current_user.account, @account)
set_relationship
render :relationship
end
def relationships
ids = params[:id].is_a?(Enumerable) ? params[:id].map(&:to_i) : [params[:id].to_i]
@accounts = Account.where(id: ids).select('id')
@following = Account.following_map(ids, current_user.account_id)
@followed_by = Account.followed_by_map(ids, current_user.account_id)
@blocking = Account.blocking_map(ids, current_user.account_id)
@muting = Account.muting_map(ids, current_user.account_id)
@requested = Account.requested_map(ids, current_user.account_id)
@domain_blocking = Account.domain_blocking_map(ids, current_user.account_id)
end
def search
@accounts = AccountSearchService.new.call(params[:q], limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:resolve] == 'true', current_account)
render :index
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end
private
@@ -135,24 +48,7 @@ class Api::V1::AccountsController < ApiController
@account = Account.find(params[:id])
end
def set_relationship
@following = Account.following_map([@account.id], current_user.account_id)
@followed_by = Account.followed_by_map([@account.id], current_user.account_id)
@blocking = Account.blocking_map([@account.id], current_user.account_id)
@muting = Account.muting_map([@account.id], current_user.account_id)
@requested = Account.requested_map([@account.id], current_user.account_id)
@domain_blocking = Account.domain_blocking_map([@account.id], current_user.account_id)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
def statuses_pagination_params(core_params)
params.permit(:limit, :only_media, :exclude_replies).merge(core_params)
end
def account_params
params.permit(:display_name, :note, :avatar, :header)
def relationships
AccountRelationshipsPresenter.new([@account.id], current_user.account_id)
end
end

View File

@@ -1,14 +1,28 @@
# frozen_string_literal: true
class Api::V1::AppsController < ApiController
class Api::V1::AppsController < Api::BaseController
respond_to :json
def create
@app = Doorkeeper::Application.create!(name: app_params[:client_name], redirect_uri: app_params[:redirect_uris], scopes: (app_params[:scopes] || Doorkeeper.configuration.default_scopes), website: app_params[:website])
@app = Doorkeeper::Application.create!(application_options)
render json: @app, serializer: REST::ApplicationSerializer
end
private
def application_options
{
name: app_params[:client_name],
redirect_uri: app_params[:redirect_uris],
scopes: app_scopes_or_default,
website: app_params[:website],
}
end
def app_scopes_or_default
app_params[:scopes] || Doorkeeper.configuration.default_scopes
end
def app_params
params.permit(:client_name, :redirect_uris, :scopes, :website)
end

View File

@@ -1,26 +1,63 @@
# frozen_string_literal: true
class Api::V1::BlocksController < ApiController
class Api::V1::BlocksController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow }
before_action :require_user!
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = Account.includes(:blocked_by)
.references(:blocked_by)
.merge(Block.where(account: current_account)
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
.to_a
next_path = api_v1_blocks_url(pagination_params(max_id: @accounts.last.blocked_by_ids.last)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = api_v1_blocks_url(pagination_params(since_id: @accounts.first.blocked_by_ids.first)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def load_accounts
default_accounts.merge(paginated_blocks).to_a
end
def default_accounts
Account.includes(:blocked_by).references(:blocked_by)
end
def paginated_blocks
Block.where(account: current_account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_blocks_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_blocks_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.blocked_by_ids.last
end
def pagination_since_id
@accounts.first.blocked_by_ids.first
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end

View File

@@ -1,18 +1,16 @@
# frozen_string_literal: true
class Api::V1::DomainBlocksController < ApiController
class Api::V1::DomainBlocksController < Api::BaseController
BLOCK_LIMIT = 100
before_action -> { doorkeeper_authorize! :follow }
before_action :require_user!
after_action :insert_pagination_headers, only: :show
respond_to :json
def show
@blocks = AccountDomainBlock.where(account: current_account).paginate_by_max_id(limit_param(100), params[:max_id], params[:since_id])
next_path = api_v1_domain_blocks_url(pagination_params(max_id: @blocks.last.id)) if @blocks.size == limit_param(100)
prev_path = api_v1_domain_blocks_url(pagination_params(since_id: @blocks.first.id)) unless @blocks.empty?
set_pagination_headers(next_path, prev_path)
@blocks = load_domain_blocks
render json: @blocks.map(&:domain)
end
@@ -28,6 +26,46 @@ class Api::V1::DomainBlocksController < ApiController
private
def load_domain_blocks
account_domain_blocks.paginate_by_max_id(
limit_param(BLOCK_LIMIT),
params[:max_id],
params[:since_id]
)
end
def account_domain_blocks
current_account.domain_blocks
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_domain_blocks_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @blocks.empty?
api_v1_domain_blocks_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@blocks.last.id
end
def pagination_since_id
@blocks.first.id
end
def records_continue?
@blocks.size == limit_param(BLOCK_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end

View File

@@ -1,25 +1,72 @@
# frozen_string_literal: true
class Api::V1::FavouritesController < ApiController
class Api::V1::FavouritesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
after_action :insert_pagination_headers
respond_to :json
def index
results = Favourite.where(account: current_account).paginate_by_max_id(limit_param(DEFAULT_STATUSES_LIMIT), params[:max_id], params[:since_id])
@statuses = cache_collection(Status.where(id: results.map(&:status_id)), Status)
set_maps(@statuses)
next_path = api_v1_favourites_url(pagination_params(max_id: results.last.id)) if results.size == limit_param(DEFAULT_STATUSES_LIMIT)
prev_path = api_v1_favourites_url(pagination_params(since_id: results.first.id)) unless results.empty?
set_pagination_headers(next_path, prev_path)
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
private
def load_statuses
cached_favourites
end
def cached_favourites
cache_collection(
Status.where(
id: results.map(&:status_id)
),
Status
)
end
def results
@_results ||= account_favourites.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def account_favourites
current_account.favourites
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_favourites_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless results.empty?
api_v1_favourites_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
results.last.id
end
def pagination_since_id
results.first.id
end
def records_continue?
results.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end

View File

@@ -1,34 +1,75 @@
# frozen_string_literal: true
class Api::V1::FollowRequestsController < ApiController
class Api::V1::FollowRequestsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow }
before_action :require_user!
after_action :insert_pagination_headers, only: :index
def index
@accounts = Account.includes(:follow_requests)
.references(:follow_requests)
.merge(FollowRequest.where(target_account: current_account)
.paginate_by_max_id(DEFAULT_ACCOUNTS_LIMIT, params[:max_id], params[:since_id]))
.to_a
next_path = api_v1_follow_requests_url(pagination_params(max_id: @accounts.last.follow_requests.last.id)) if @accounts.size == DEFAULT_ACCOUNTS_LIMIT
prev_path = api_v1_follow_requests_url(pagination_params(since_id: @accounts.first.follow_requests.first.id)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
def authorize
AuthorizeFollowService.new.call(Account.find(params[:id]), current_account)
AuthorizeFollowService.new.call(account, current_account)
render_empty
end
def reject
RejectFollowService.new.call(Account.find(params[:id]), current_account)
RejectFollowService.new.call(account, current_account)
render_empty
end
private
def account
Account.find(params[:id])
end
def load_accounts
default_accounts.merge(paginated_follow_requests).to_a
end
def default_accounts
Account.includes(:follow_requests).references(:follow_requests)
end
def paginated_follow_requests
FollowRequest.where(target_account: current_account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_follow_requests_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_follow_requests_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.follow_requests.last.id
end
def pagination_since_id
@accounts.first.follow_requests.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end

View File

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V1::FollowsController < ApiController
class Api::V1::FollowsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow }
before_action :require_user!
@@ -10,7 +10,7 @@ class Api::V1::FollowsController < ApiController
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
render :show
render json: @account, serializer: REST::AccountSerializer
end
private

View File

@@ -1,7 +1,9 @@
# frozen_string_literal: true
class Api::V1::InstancesController < ApiController
class Api::V1::InstancesController < Api::BaseController
respond_to :json
def show; end
def show
render json: {}, serializer: REST::InstanceSerializer
end
end

View File

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V1::MediaController < ApiController
class Api::V1::MediaController < Api::BaseController
before_action -> { doorkeeper_authorize! :write }
before_action :require_user!
@@ -10,11 +10,12 @@ class Api::V1::MediaController < ApiController
respond_to :json
def create
@media = MediaAttachment.create!(account: current_user.account, file: media_params[:file])
@media = current_account.media_attachments.create!(file: media_params[:file])
render json: @media, serializer: REST::MediaAttachmentSerializer
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
render json: { error: 'File type of uploaded media could not be verified' }, status: 422
render json: file_type_error, status: 422
rescue Paperclip::Error
render json: { error: 'Error processing thumbnail for uploaded media' }, status: 500
render json: processing_error, status: 500
end
private
@@ -22,4 +23,12 @@ class Api::V1::MediaController < ApiController
def media_params
params.permit(:file)
end
def file_type_error
{ error: 'File type of uploaded media could not be verified' }
end
def processing_error
{ error: 'Error processing thumbnail for uploaded media' }
end
end

View File

@@ -1,26 +1,63 @@
# frozen_string_literal: true
class Api::V1::MutesController < ApiController
class Api::V1::MutesController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow }
before_action :require_user!
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = Account.includes(:muted_by)
.references(:muted_by)
.merge(Mute.where(account: current_account)
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
.to_a
next_path = api_v1_mutes_url(pagination_params(max_id: @accounts.last.muted_by_ids.last)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = api_v1_mutes_url(pagination_params(since_id: @accounts.first.muted_by_ids.first)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def load_accounts
default_accounts.merge(paginated_mutes).to_a
end
def default_accounts
Account.includes(:muted_by).references(:muted_by)
end
def paginated_mutes
Mute.where(account: current_account).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_mutes_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_mutes_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.muted_by_ids.last
end
def pagination_since_id
@accounts.first.muted_by_ids.first
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end

View File

@@ -1,42 +1,80 @@
# frozen_string_literal: true
class Api::V1::NotificationsController < ApiController
class Api::V1::NotificationsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
after_action :insert_pagination_headers, only: :index
respond_to :json
DEFAULT_NOTIFICATIONS_LIMIT = 15
def index
@notifications = Notification.where(account: current_account).browserable(exclude_types).paginate_by_max_id(limit_param(DEFAULT_NOTIFICATIONS_LIMIT), params[:max_id], params[:since_id])
@notifications = cache_collection(@notifications, Notification)
statuses = @notifications.select { |n| !n.target_status.nil? }.map(&:target_status)
set_maps(statuses)
next_path = api_v1_notifications_url(pagination_params(max_id: @notifications.last.id)) unless @notifications.empty?
prev_path = api_v1_notifications_url(pagination_params(since_id: @notifications.first.id)) unless @notifications.empty?
set_pagination_headers(next_path, prev_path)
@notifications = load_notifications
render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
end
def show
@notification = Notification.where(account: current_account).find(params[:id])
@notification = current_account.notifications.find(params[:id])
render json: @notification, serializer: REST::NotificationSerializer
end
def clear
Notification.where(account: current_account).delete_all
current_account.notifications.delete_all
render_empty
end
def dismiss
Notification.find_by!(account: current_account, id: params[:id]).destroy!
current_account.notifications.find_by!(id: params[:id]).destroy!
render_empty
end
private
def load_notifications
cache_collection paginated_notifications, Notification
end
def paginated_notifications
browserable_account_notifications.paginate_by_max_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def browserable_account_notifications
current_account.notifications.browserable(exclude_types)
end
def target_statuses_from_notifications
@notifications.reject { |notification| notification.target_status.nil? }.map(&:target_status)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
unless @notifications.empty?
api_v1_notifications_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @notifications.empty?
api_v1_notifications_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@notifications.last.id
end
def pagination_since_id
@notifications.first.id
end
def exclude_types
val = params.permit(exclude_types: [])[:exclude_types] || []
val = [val] unless val.is_a?(Enumerable)

View File

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V1::ReportsController < ApiController
class Api::V1::ReportsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, except: [:create]
before_action -> { doorkeeper_authorize! :write }, only: [:create]
before_action :require_user!
@@ -8,22 +8,36 @@ class Api::V1::ReportsController < ApiController
respond_to :json
def index
@reports = Report.where(account: current_account)
@reports = current_account.reports
render json: @reports, each_serializer: REST::ReportSerializer
end
def create
status_ids = report_params[:status_ids].is_a?(Enumerable) ? report_params[:status_ids] : [report_params[:status_ids]]
@report = current_account.reports.create!(
target_account: reported_account,
status_ids: reported_status_ids,
comment: report_params[:comment]
)
@report = Report.create!(account: current_account,
target_account: Account.find(report_params[:account_id]),
status_ids: Status.find(status_ids).pluck(:id),
comment: report_params[:comment])
User.admins.includes(:account).each { |u| AdminMailer.new_report(u.account, @report).deliver_later }
render :show
render json: @report, serializer: REST::ReportSerializer
end
private
def reported_status_ids
Status.find(status_ids).pluck(:id)
end
def status_ids
Array(report_params[:status_ids])
end
def reported_account
Account.find(report_params[:account_id])
end
def report_params
params.permit(:account_id, :comment, status_ids: [])
end

View File

@@ -1,9 +1,30 @@
# frozen_string_literal: true
class Api::V1::SearchController < ApiController
class Api::V1::SearchController < Api::BaseController
RESULTS_LIMIT = 5
before_action -> { doorkeeper_authorize! :read }
before_action :require_user!
respond_to :json
def index
@search = OpenStruct.new(SearchService.new.call(params[:q], 5, params[:resolve] == 'true', current_account))
@search = Search.new(search_results)
render json: @search, serializer: REST::SearchSerializer
end
private
def search_results
SearchService.new.call(
params[:q],
RESULTS_LIMIT,
resolving_search?,
current_account
)
end
def resolving_search?
params[:resolve] == 'true'
end
end

View File

@@ -0,0 +1,82 @@
# frozen_string_literal: true
class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
include Authorization
before_action :authorize_if_got_token
before_action :set_status
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def load_accounts
default_accounts.merge(paginated_favourites).to_a
end
def default_accounts
Account
.includes(:favourites)
.references(:favourites)
.where(favourites: { status_id: @status.id })
end
def paginated_favourites
Favourite.paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_status_favourited_by_index_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_status_favourited_by_index_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.favourites.last.id
end
def pagination_since_id
@accounts.first.favourites.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code
raise ActiveRecord::RecordNotFound
end
def authorize_if_got_token
request_token = Doorkeeper::OAuth::Token.from_request(request, *Doorkeeper.configuration.access_token_methods)
doorkeeper_authorize! :read if request_token
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
end

View File

@@ -0,0 +1,38 @@
# frozen_string_literal: true
class Api::V1::Statuses::FavouritesController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write }
before_action :require_user!
respond_to :json
def create
@status = favourited_status
render json: @status, serializer: REST::StatusSerializer
end
def destroy
@status = requested_status
@favourites_map = { @status.id => false }
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
end
private
def favourited_status
service_result.status.reload
end
def service_result
FavouriteService.new.call(current_user.account, requested_status)
end
def requested_status
Status.find(params[:status_id])
end
end

View File

@@ -0,0 +1,41 @@
# frozen_string_literal: true
class Api::V1::Statuses::MutesController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write }
before_action :require_user!
before_action :set_status
before_action :set_conversation
respond_to :json
def create
current_account.mute_conversation!(@conversation)
@mutes_map = { @conversation.id => true }
render json: @status, serializer: REST::StatusSerializer
end
def destroy
current_account.unmute_conversation!(@conversation)
@mutes_map = { @conversation.id => false }
render json: @status, serializer: REST::StatusSerializer
end
private
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code
raise ActiveRecord::RecordNotFound
end
def set_conversation
@conversation = @status.conversation
raise Mastodon::ValidationError if @conversation.nil?
end
end

View File

@@ -0,0 +1,79 @@
# frozen_string_literal: true
class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
include Authorization
before_action :authorize_if_got_token
before_action :set_status
after_action :insert_pagination_headers
respond_to :json
def index
@accounts = load_accounts
render json: @accounts, each_serializer: REST::AccountSerializer
end
private
def load_accounts
default_accounts.merge(paginated_statuses).to_a
end
def default_accounts
Account.includes(:statuses).references(:statuses)
end
def paginated_statuses
Status.where(reblog_of_id: @status.id).paginate_by_max_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params[:max_id],
params[:since_id]
)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
if records_continue?
api_v1_status_reblogged_by_index_url pagination_params(max_id: pagination_max_id)
end
end
def prev_path
unless @accounts.empty?
api_v1_status_reblogged_by_index_url pagination_params(since_id: pagination_since_id)
end
end
def pagination_max_id
@accounts.last.statuses.last.id
end
def pagination_since_id
@accounts.first.statuses.first.id
end
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def set_status
@status = Status.find(params[:status_id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code
raise ActiveRecord::RecordNotFound
end
def authorize_if_got_token
request_token = Doorkeeper::OAuth::Token.from_request(request, *Doorkeeper.configuration.access_token_methods)
doorkeeper_authorize! :read if request_token
end
def pagination_params(core_params)
params.permit(:limit).merge(core_params)
end
end

View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true
class Api::V1::Statuses::ReblogsController < Api::BaseController
include Authorization
before_action -> { doorkeeper_authorize! :write }
before_action :require_user!
respond_to :json
def create
@status = ReblogService.new.call(current_user.account, status_for_reblog)
render json: @status, serializer: REST::StatusSerializer
end
def destroy
@status = status_for_destroy.reblog
@reblogs_map = { @status.id => false }
authorize status_for_destroy, :unreblog?
RemovalWorker.perform_async(status_for_destroy.id)
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map)
end
private
def status_for_reblog
Status.find params[:status_id]
end
def status_for_destroy
current_user.account.statuses.where(reblog_of_id: params[:status_id]).first!
end
end

View File

@@ -1,17 +1,19 @@
# frozen_string_literal: true
class Api::V1::StatusesController < ApiController
before_action :authorize_if_got_token, except: [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite, :mute, :unmute]
before_action -> { doorkeeper_authorize! :write }, only: [:create, :destroy, :reblog, :unreblog, :favourite, :unfavourite, :mute, :unmute]
before_action :require_user!, except: [:show, :context, :card, :reblogged_by, :favourited_by]
before_action :set_status, only: [:show, :context, :card, :reblogged_by, :favourited_by, :mute, :unmute]
before_action :set_conversation, only: [:mute, :unmute]
class Api::V1::StatusesController < Api::BaseController
include Authorization
before_action :authorize_if_got_token, except: [:create, :destroy]
before_action -> { doorkeeper_authorize! :write }, only: [:create, :destroy]
before_action :require_user!, except: [:show, :context, :card]
before_action :set_status, only: [:show, :context, :card]
respond_to :json
def show
cached = Rails.cache.read(@status.cache_key)
@status = cached unless cached.nil?
render json: @status, serializer: REST::StatusSerializer
end
def context
@@ -20,45 +22,20 @@ class Api::V1::StatusesController < ApiController
loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status)
@context = OpenStruct.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
statuses = [@status] + @context[:ancestors] + @context[:descendants]
@context = Context.new(ancestors: loaded_ancestors, descendants: loaded_descendants)
statuses = [@status] + @context.ancestors + @context.descendants
set_maps(statuses)
render json: @context, serializer: REST::ContextSerializer, relationships: StatusRelationshipsPresenter.new(statuses, current_user&.account_id)
end
def card
@card = PreviewCard.find_by(status: @status)
render_empty if @card.nil?
end
def reblogged_by
@accounts = Account.includes(:statuses)
.references(:statuses)
.merge(Status.where(reblog_of_id: @status.id)
.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
.to_a
next_path = reblogged_by_api_v1_status_url(pagination_params(max_id: @accounts.last.statuses.last.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = reblogged_by_api_v1_status_url(pagination_params(since_id: @accounts.first.statuses.first.id)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
render :accounts
end
def favourited_by
@accounts = Account.includes(:favourites)
.references(:favourites)
.where(favourites: { status_id: @status.id })
.merge(Favourite.paginate_by_max_id(limit_param(DEFAULT_ACCOUNTS_LIMIT), params[:max_id], params[:since_id]))
.to_a
next_path = favourited_by_api_v1_status_url(pagination_params(max_id: @accounts.last.favourites.last.id)) if @accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
prev_path = favourited_by_api_v1_status_url(pagination_params(since_id: @accounts.first.favourites.first.id)) unless @accounts.empty?
set_pagination_headers(next_path, prev_path)
render :accounts
if @card.nil?
render_empty
else
render json: @card, serializer: REST::PreviewCardSerializer
end
end
def create
@@ -72,70 +49,26 @@ class Api::V1::StatusesController < ApiController
application: doorkeeper_token.application,
idempotency: request.headers['Idempotency-Key'])
render :show
render json: @status, serializer: REST::StatusSerializer
end
def destroy
@status = Status.where(account_id: current_user.account).find(params[:id])
authorize @status, :destroy?
RemovalWorker.perform_async(@status.id)
render_empty
end
def reblog
@status = ReblogService.new.call(current_user.account, Status.find(params[:id]))
render :show
end
def unreblog
reblog = Status.where(account_id: current_user.account, reblog_of_id: params[:id]).first!
@status = reblog.reblog
@reblogs_map = { @status.id => false }
RemovalWorker.perform_async(reblog.id)
render :show
end
def favourite
@status = FavouriteService.new.call(current_user.account, Status.find(params[:id])).status.reload
render :show
end
def unfavourite
@status = Status.find(params[:id])
@favourites_map = { @status.id => false }
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
render :show
end
def mute
current_account.mute_conversation!(@conversation)
@mutes_map = { @conversation.id => true }
render :show
end
def unmute
current_account.unmute_conversation!(@conversation)
@mutes_map = { @conversation.id => false }
render :show
end
private
def set_status
@status = Status.find(params[:id])
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
end
def set_conversation
@conversation = @status.conversation
raise Mastodon::ValidationError if @conversation.nil?
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code
raise ActiveRecord::RecordNotFound
end
def status_params

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
class Api::V1::StreamingController < Api::BaseController
respond_to :json
def index
if Rails.configuration.x.streaming_api_base_url != request.host
uri = URI.parse(request.url)
uri.host = URI.parse(Rails.configuration.x.streaming_api_base_url).host
redirect_to uri.to_s, status: 301
else
raise ActiveRecord::RecordNotFound
end
end
end

View File

@@ -1,30 +0,0 @@
# frozen_string_literal: true
module Api::V1::Timelines
class BaseController < ApiController
respond_to :json
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
private
def cache_collection(raw)
super(raw, Status)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def next_path
raise 'Override in child controllers'
end
def prev_path
raise 'Override in child controllers'
end
end
end

View File

@@ -1,44 +1,60 @@
# frozen_string_literal: true
module Api::V1::Timelines
class HomeController < BaseController
before_action -> { doorkeeper_authorize! :read }, only: [:show]
before_action :require_user!, only: [:show]
class Api::V1::Timelines::HomeController < Api::BaseController
before_action -> { doorkeeper_authorize! :read }, only: [:show]
before_action :require_user!, only: [:show]
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show
@statuses = load_statuses
end
respond_to :json
private
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
def load_statuses
cached_home_statuses.tap do |statuses|
set_maps(statuses)
end
end
private
def cached_home_statuses
cache_collection home_statuses
end
def load_statuses
cached_home_statuses
end
def home_statuses
account_home_feed.get(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def cached_home_statuses
cache_collection home_statuses, Status
end
def account_home_feed
Feed.new(:home, current_account)
end
def home_statuses
account_home_feed.get(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def next_path
api_v1_timelines_home_url pagination_params(max_id: @statuses.last.id)
end
def account_home_feed
Feed.new(:home, current_account)
end
def prev_path
api_v1_timelines_home_url pagination_params(since_id: @statuses.first.id)
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
def next_path
api_v1_timelines_home_url pagination_params(max_id: pagination_max_id)
end
def prev_path
api_v1_timelines_home_url pagination_params(since_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -1,41 +1,58 @@
# frozen_string_literal: true
module Api::V1::Timelines
class PublicController < BaseController
def show
@statuses = load_statuses
end
class Api::V1::Timelines::PublicController < Api::BaseController
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
private
respond_to :json
def load_statuses
cached_public_statuses.tap do |statuses|
set_maps(statuses)
end
end
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
def cached_public_statuses
cache_collection public_statuses
end
private
def public_statuses
public_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def load_statuses
cached_public_statuses
end
def public_timeline_statuses
Status.as_public_timeline(current_account, params[:local])
end
def cached_public_statuses
cache_collection public_statuses, Status
end
def next_path
api_v1_timelines_public_url pagination_params(max_id: @statuses.last.id)
end
def public_statuses
public_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
def prev_path
api_v1_timelines_public_url pagination_params(since_id: @statuses.first.id)
end
def public_timeline_statuses
Status.as_public_timeline(current_account, params[:local])
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
def next_path
api_v1_timelines_public_url pagination_params(max_id: pagination_max_id)
end
def prev_path
api_v1_timelines_public_url pagination_params(since_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -1,51 +1,67 @@
# frozen_string_literal: true
module Api::V1::Timelines
class TagController < BaseController
before_action :load_tag
class Api::V1::Timelines::TagController < Api::BaseController
before_action :load_tag
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
def show
@statuses = load_statuses
end
respond_to :json
private
def show
@statuses = load_statuses
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
end
def load_tag
@tag = Tag.find_by(name: params[:id].downcase)
end
private
def load_statuses
cached_tagged_statuses.tap do |statuses|
set_maps(statuses)
end
end
def load_tag
@tag = Tag.find_by(name: params[:id].downcase)
end
def cached_tagged_statuses
cache_collection tagged_statuses
end
def load_statuses
cached_tagged_statuses
end
def tagged_statuses
if @tag.nil?
[]
else
tag_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
end
def cached_tagged_statuses
cache_collection tagged_statuses, Status
end
def tag_timeline_statuses
Status.as_tag_timeline(@tag, current_account, params[:local])
end
def next_path
api_v1_timelines_tag_url params[:id], pagination_params(max_id: @statuses.last.id)
end
def prev_path
api_v1_timelines_tag_url params[:id], pagination_params(since_id: @statuses.first.id)
def tagged_statuses
if @tag.nil?
[]
else
tag_timeline_statuses.paginate_by_max_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params[:max_id],
params[:since_id]
)
end
end
def tag_timeline_statuses
Status.as_tag_timeline(@tag, current_account, params[:local])
end
def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end
def pagination_params(core_params)
params.permit(:local, :limit).merge(core_params)
end
def next_path
api_v1_timelines_tag_url params[:id], pagination_params(max_id: pagination_max_id)
end
def prev_path
api_v1_timelines_tag_url params[:id], pagination_params(since_id: pagination_since_id)
end
def pagination_max_id
@statuses.last.id
end
def pagination_since_id
@statuses.first.id
end
end

View File

@@ -0,0 +1,52 @@
# frozen_string_literal: true
class Api::Web::PushSubscriptionsController < Api::BaseController
respond_to :json
before_action :require_user!
def create
params.require(:subscription).require(:endpoint)
params.require(:subscription).require(:keys).require([:auth, :p256dh])
active_session = current_session
unless active_session.web_push_subscription.nil?
active_session.web_push_subscription.destroy!
active_session.update!(web_push_subscription: nil)
end
# Mobile devices do not support regular notifications, so we enable push notifications by default
alerts_enabled = active_session.detection.device.mobile? || active_session.detection.device.tablet?
data = {
alerts: {
follow: alerts_enabled,
favourite: alerts_enabled,
reblog: alerts_enabled,
mention: alerts_enabled,
},
}
web_subscription = ::Web::PushSubscription.create!(
endpoint: params[:subscription][:endpoint],
key_p256dh: params[:subscription][:keys][:p256dh],
key_auth: params[:subscription][:keys][:auth],
data: data
)
active_session.update!(web_push_subscription: web_subscription)
render json: web_subscription.as_payload
end
def update
params.require([:id, :data])
web_subscription = ::Web::PushSubscription.find(params[:id])
web_subscription.update!(data: params[:data])
render json: web_subscription.as_payload
end
end

View File

@@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::Web::SettingsController < ApiController
class Api::Web::SettingsController < Api::BaseController
respond_to :json
before_action :require_user!

View File

@@ -11,6 +11,7 @@ class ApplicationController < ActionController::Base
include UserTrackingConcern
helper_method :current_account
helper_method :current_session
helper_method :single_user_mode?
rescue_from ActionController::RoutingError, with: :not_found
@@ -68,6 +69,10 @@ class ApplicationController < ActionController::Base
@current_account ||= current_user.try(:account)
end
def current_session
@current_session ||= SessionActivation.find_by(session_id: cookies.signed['_session_id'])
end
def cache_collection(raw, klass)
return raw unless klass.respond_to?(:with_includes)

View File

@@ -5,6 +5,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :check_enabled_registrations, only: [:new, :create]
before_action :configure_sign_up_params, only: [:create]
before_action :set_sessions, only: [:edit, :update]
def destroy
not_found
@@ -41,4 +42,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
def determine_layout
%w(edit update).include?(action_name) ? 'admin' : 'auth'
end
def set_sessions
@sessions = current_user.session_activations
end
end

View File

@@ -12,13 +12,13 @@ class Auth::SessionsController < Devise::SessionsController
def create
super do |resource|
remember_me(resource)
flash[:notice] = nil
flash.delete(:notice)
end
end
def destroy
super
flash[:notice] = nil
flash.delete(:notice)
end
protected
@@ -27,7 +27,7 @@ class Auth::SessionsController < Devise::SessionsController
if session[:otp_user_id]
User.find(session[:otp_user_id])
elsif user_params[:email]
User.find_by(email: user_params[:email])
User.find_for_authentication(email: user_params[:email])
end
end

View File

@@ -15,7 +15,7 @@ class AuthorizeFollowsController < ApplicationController
if @account.nil?
render :error
else
redirect_to web_url("accounts/#{@account.id}")
render :success
end
rescue ActiveRecord::RecordNotFound, Mastodon::NotPermittedError
render :error
@@ -40,7 +40,7 @@ class AuthorizeFollowsController < ApplicationController
end
def account_from_remote_follow
FollowRemoteAccountService.new.call(acct_without_prefix)
ResolveRemoteAccountService.new.call(acct_without_prefix)
end
def acct_param_is_url?

View File

@@ -0,0 +1,22 @@
# frozen_string_literal: true
module Authorization
extend ActiveSupport::Concern
include Pundit
def pundit_user
current_account
end
def authorize(*)
super
rescue Pundit::NotAuthorizedError
raise Mastodon::NotPermittedError
end
def authorize_with(user, record, query)
Pundit.authorize(user, record, query)
rescue Pundit::NotAuthorizedError
raise Mastodon::NotPermittedError
end
end

View File

@@ -0,0 +1,30 @@
# frozen_string_literal: true
module ExportControllerConcern
extend ActiveSupport::Concern
included do
before_action :authenticate_user!
before_action :load_export
end
private
def load_export
@export = Export.new(current_account)
end
def send_export_file
respond_to do |format|
format.csv { send_data export_data, filename: export_filename }
end
end
def export_data
raise 'Override in controller'
end
def export_filename
"#{controller_name}.csv"
end
end

View File

@@ -17,12 +17,24 @@ module Localized
end
def default_locale
ENV.fetch('DEFAULT_LOCALE') do
user_supplied_locale || I18n.default_locale
end
request_locale || env_locale || I18n.default_locale
end
def user_supplied_locale
http_accept_language.language_region_compatible_from(I18n.available_locales)
def env_locale
ENV['DEFAULT_LOCALE']
end
def request_locale
preferred_locale || compatible_locale
end
def preferred_locale
http_accept_language.preferred_language_from([env_locale]) ||
http_accept_language.preferred_language_from(I18n.available_locales)
end
def compatible_locale
http_accept_language.compatible_language_from([env_locale]) ||
http_accept_language.compatible_language_from(I18n.available_locales)
end
end

View File

@@ -4,19 +4,13 @@ module ObfuscateFilename
extend ActiveSupport::Concern
class_methods do
def obfuscate_filename(*args)
before_action { obfuscate_filename(*args) }
def obfuscate_filename(path)
before_action do
file = params.dig(*path)
next if file.nil?
file.original_filename = SecureRandom.hex(8) + File.extname(file.original_filename)
end
end
end
def obfuscate_filename(path)
file = params.dig(*path)
return if file.nil?
file.original_filename = secure_token + File.extname(file.original_filename)
end
def secure_token(length = 16)
SecureRandom.hex(length / 2)
end
end

View File

@@ -0,0 +1,57 @@
# frozen_string_literal: true
module RateLimitHeaders
extend ActiveSupport::Concern
included do
before_action :set_rate_limit_headers, if: :rate_limited_request?
end
private
def set_rate_limit_headers
apply_header_limit
apply_header_remaining
apply_header_reset
end
def rate_limited_request?
!request.env['rack.attack.throttle_data'].nil?
end
def apply_header_limit
response.headers['X-RateLimit-Limit'] = rate_limit_limit
end
def rate_limit_limit
api_throttle_data[:limit].to_s
end
def apply_header_remaining
response.headers['X-RateLimit-Remaining'] = rate_limit_remaining
end
def rate_limit_remaining
(api_throttle_data[:limit] - api_throttle_data[:count]).to_s
end
def apply_header_reset
response.headers['X-RateLimit-Reset'] = rate_limit_reset
end
def rate_limit_reset
(request_time + reset_period_offset).iso8601(6)
end
def api_throttle_data
request.env['rack.attack.throttle_data']['api']
end
def request_time
@_request_time ||= Time.now.utc
end
def reset_period_offset
api_throttle_data[:period] - request_time.to_i % api_throttle_data[:period]
end
end

View File

@@ -0,0 +1,87 @@
# frozen_string_literal: true
# Implemented according to HTTP signatures (Draft 6)
# <https://tools.ietf.org/html/draft-cavage-http-signatures-06>
module SignatureVerification
extend ActiveSupport::Concern
def signed_request?
request.headers['Signature'].present?
end
def signed_request_account
return @signed_request_account if defined?(@signed_request_account)
unless signed_request?
@signed_request_account = nil
return
end
raw_signature = request.headers['Signature']
signature_params = {}
raw_signature.split(',').each do |part|
parsed_parts = part.match(/([a-z]+)="([^"]+)"/i)
next if parsed_parts.nil? || parsed_parts.size != 3
signature_params[parsed_parts[1]] = parsed_parts[2]
end
if incompatible_signature?(signature_params)
@signed_request_account = nil
return
end
account = ResolveRemoteAccountService.new.call(signature_params['keyId'].gsub(/\Aacct:/, ''))
if account.nil?
@signed_request_account = nil
return
end
signature = Base64.decode64(signature_params['signature'])
compare_signed_string = build_signed_string(signature_params['headers'])
if account.keypair.public_key.verify(OpenSSL::Digest::SHA256.new, signature, compare_signed_string)
@signed_request_account = account
@signed_request_account
else
@signed_request_account = nil
end
end
private
def build_signed_string(signed_headers)
signed_headers = 'date' if signed_headers.blank?
signed_headers.split(' ').map do |signed_header|
if signed_header == Request::REQUEST_TARGET
"#{Request::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
else
"#{signed_header}: #{request.headers[to_header_name(signed_header)]}"
end
end.join("\n")
end
def matches_time_window?
begin
time_sent = DateTime.httpdate(request.headers['Date'])
rescue ArgumentError
return false
end
(Time.now.utc - time_sent).abs <= 30
end
def to_header_name(name)
name.split(/-/).map(&:capitalize).join('-')
end
def incompatible_signature?(signature_params)
signature_params['keyId'].blank? ||
signature_params['signature'].blank? ||
signature_params['algorithm'].blank? ||
signature_params['algorithm'] != 'rsa-sha256' ||
!signature_params['keyId'].start_with?('acct:')
end
end

View File

@@ -17,7 +17,7 @@ module UserTrackingConcern
current_user.update_tracked_fields!(request)
# Regenerate feed if needed
RegenerationWorker.perform_async(current_user.account_id) if user_needs_feed_update?
regenerate_feed! if user_needs_feed_update?
end
def user_needs_sign_in_update?
@@ -27,4 +27,9 @@ module UserTrackingConcern
def user_needs_feed_update?
current_user.last_sign_in_at < REGENERATE_FEED_DAYS.days.ago
end
def regenerate_feed!
Redis.current.setnx("account:#{current_user.account_id}:regeneration", true) == 1 && Redis.current.expire("account:#{current_user.account_id}:regeneration", 3_600 * 24)
RegenerationWorker.perform_async(current_user.account_id)
end
end

View File

@@ -5,5 +5,24 @@ class FollowerAccountsController < ApplicationController
def index
@follows = Follow.where(target_account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:account)
respond_to do |format|
format.html
format.json do
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
end
end
end
private
def collection_presenter
ActivityPub::CollectionPresenter.new(
id: account_followers_url(@account),
type: :ordered,
size: @account.followers_count,
items: @follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.account) }
)
end
end

View File

@@ -5,5 +5,24 @@ class FollowingAccountsController < ApplicationController
def index
@follows = Follow.where(account: @account).recent.page(params[:page]).per(FOLLOW_PER_PAGE).preload(:target_account)
respond_to do |format|
format.html
format.json do
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
end
end
end
private
def collection_presenter
ActivityPub::CollectionPresenter.new(
id: account_following_index_url(@account),
type: :ordered,
size: @account.following_count,
items: @follows.map { |f| ActivityPub::TagManager.instance.uri_for(f.target_account) }
)
end
end

View File

@@ -2,13 +2,10 @@
class HomeController < ApplicationController
before_action :authenticate_user!
before_action :set_initial_state_json
def index
@body_classes = 'app-body'
@token = find_or_create_access_token.token
@web_settings = Web::Setting.find_by(user: current_user)&.data || {}
@admin = Account.find_local(Setting.site_contact_username)
@streaming_api_base_url = Rails.configuration.x.streaming_api_base_url
@body_classes = 'app-body'
end
private
@@ -17,13 +14,18 @@ class HomeController < ApplicationController
redirect_to(single_user_mode? ? account_path(Account.first) : about_path) unless user_signed_in?
end
def find_or_create_access_token
Doorkeeper::AccessToken.find_or_create_for(
Doorkeeper::Application.where(superapp: true).first,
current_user.id,
Doorkeeper::OAuth::Scopes.from_string('read write follow'),
Doorkeeper.configuration.access_token_expires_in,
Doorkeeper.configuration.refresh_token_enabled?
)
def set_initial_state_json
serializable_resource = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(initial_state_params), serializer: InitialStateSerializer)
@initial_state_json = serializable_resource.to_json
end
def initial_state_params
{
settings: Web::Setting.find_by(user: current_user)&.data || {},
push_subscription: current_account.user.web_push_subscription(current_session),
current_account: current_account,
token: current_session.token,
admin: Account.find_local(Setting.site_contact_username),
}
end
end

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
class ManifestsController < ApplicationController
before_action :set_instance_presenter
def show; end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
end

View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true
class MediaController < ApplicationController
include Authorization
before_action :verify_permitted_status
def show
@@ -14,6 +16,9 @@ class MediaController < ApplicationController
end
def verify_permitted_status
raise ActiveRecord::RecordNotFound unless media_attachment.status.permitted?(current_account)
authorize media_attachment.status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code
raise ActiveRecord::RecordNotFound
end
end

View File

@@ -0,0 +1,32 @@
# frozen_string_literal: true
class Settings::DeletesController < ApplicationController
layout 'admin'
before_action :check_enabled_deletion
before_action :authenticate_user!
def show
@confirmation = Form::DeleteConfirmation.new
end
def destroy
if current_user.valid_password?(delete_params[:password])
Admin::SuspensionWorker.perform_async(current_user.account_id, true)
sign_out
redirect_to new_user_session_path, notice: I18n.t('deletes.success_msg')
else
redirect_to settings_delete_path, alert: I18n.t('deletes.bad_password_msg')
end
end
private
def check_enabled_deletion
redirect_to root_path unless Setting.open_deletion
end
def delete_params
params.require(:form_delete_confirmation).permit(:password)
end
end

View File

@@ -1,23 +0,0 @@
# frozen_string_literal: true
module Settings
module Exports
class BaseController < ApplicationController
before_action :authenticate_user!
def index
@export = Export.new(current_account)
respond_to do |format|
format.csv { send_data export_data, filename: export_filename }
end
end
private
def export_filename
"#{controller_name}.csv"
end
end
end
end

View File

@@ -2,7 +2,13 @@
module Settings
module Exports
class BlockedAccountsController < BaseController
class BlockedAccountsController < ApplicationController
include ExportControllerConcern
def index
send_export_file
end
private
def export_data

View File

@@ -2,7 +2,13 @@
module Settings
module Exports
class FollowingAccountsController < BaseController
class FollowingAccountsController < ApplicationController
include ExportControllerConcern
def index
send_export_file
end
private
def export_data

View File

@@ -2,7 +2,13 @@
module Settings
module Exports
class MutedAccountsController < BaseController
class MutedAccountsController < ApplicationController
include ExportControllerConcern
def index
send_export_file
end
private
def export_data

View File

@@ -1,5 +1,7 @@
# frozen_string_literal: true
require 'sidekiq-bulk'
class Settings::FollowerDomainsController < ApplicationController
layout 'admin'
@@ -13,8 +15,8 @@ class Settings::FollowerDomainsController < ApplicationController
def update
domains = bulk_params[:select] || []
domains.each do |domain|
SoftBlockDomainFollowersWorker.perform_async(current_account.id, domain)
SoftBlockDomainFollowersWorker.push_bulk(domains) do |domain|
[current_account.id, domain]
end
redirect_to settings_follower_domains_path, notice: I18n.t('followers.success', count: domains.size)

View File

@@ -34,8 +34,13 @@ class Settings::PreferencesController < ApplicationController
def user_settings_params
params.require(:user).permit(
:setting_default_privacy,
:setting_default_sensitive,
:setting_unfollow_modal,
:setting_boost_modal,
:setting_delete_modal,
:setting_auto_play_gif,
:setting_system_font_ui,
:setting_noindex,
notification_emails: %i(follow follow_request reblog favourite mention digest),
interactions: %i(must_be_follower must_be_following)
)

View File

@@ -0,0 +1,17 @@
# frozen_string_literal: true
class Settings::SessionsController < ApplicationController
before_action :set_session, only: :destroy
def destroy
@session.destroy!
flash[:notice] = I18n.t('sessions.revoke_success')
redirect_to edit_user_registration_path
end
private
def set_session
@session = current_user.session_activations.find(params[:id])
end
end

View File

@@ -7,7 +7,9 @@ module Settings
before_action :authenticate_user!
before_action :verify_otp_required, only: [:create]
def show; end
def show
@confirmation = Form::TwoFactorConfirmation.new
end
def create
current_user.otp_secret = User.generate_otp_secret(32)
@@ -16,13 +18,23 @@ module Settings
end
def destroy
current_user.otp_required_for_login = false
current_user.save!
redirect_to settings_two_factor_authentication_path
if current_user.validate_and_consume_otp!(confirmation_params[:code])
current_user.otp_required_for_login = false
current_user.save!
redirect_to settings_two_factor_authentication_path
else
flash.now[:alert] = I18n.t('two_factor_authentication.wrong_code')
@confirmation = Form::TwoFactorConfirmation.new
render :show
end
end
private
def confirmation_params
params.require(:form_two_factor_confirmation).permit(:code)
end
def verify_otp_required
redirect_to settings_two_factor_authentication_path if current_user.otp_required_for_login?
end

View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true
class StatusesController < ApplicationController
include Authorization
layout 'public'
before_action :set_account
@@ -9,10 +11,22 @@ class StatusesController < ApplicationController
before_action :check_account_suspension
def show
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
@descendants = cache_collection(@status.descendants(current_account), Status)
respond_to do |format|
format.html do
@ancestors = @status.reply? ? cache_collection(@status.ancestors(current_account), Status) : []
@descendants = cache_collection(@status.descendants(current_account), Status)
render 'stream_entries/show'
render 'stream_entries/show'
end
format.json do
render json: @status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter
end
end
end
def activity
render json: @status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter
end
private
@@ -30,7 +44,10 @@ class StatusesController < ApplicationController
@stream_entry = @status.stream_entry
@type = @stream_entry.activity_type.downcase
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
authorize @status, :show?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404
raise ActiveRecord::RecordNotFound
end
def check_account_suspension

View File

@@ -1,6 +1,9 @@
# frozen_string_literal: true
class StreamEntriesController < ApplicationController
include Authorization
include SignatureVerification
layout 'public'
before_action :set_account
@@ -16,7 +19,7 @@ class StreamEntriesController < ApplicationController
end
format.atom do
render xml: AtomSerializer.render(AtomSerializer.new.entry(@stream_entry, true))
render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.entry(@stream_entry, true))
end
end
end
@@ -42,7 +45,11 @@ class StreamEntriesController < ApplicationController
@stream_entry = @account.stream_entries.where(activity_type: 'Status').find(params[:id])
@type = @stream_entry.activity_type.downcase
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil? || (@stream_entry.hidden? && !@stream_entry.activity.permitted?(current_account))
raise ActiveRecord::RecordNotFound if @stream_entry.activity.nil?
authorize @stream_entry.activity, :show? if @stream_entry.hidden?
rescue Mastodon::NotPermittedError
# Reraise in order to get a 404
raise ActiveRecord::RecordNotFound
end
def check_account_suspension

View File

@@ -5,7 +5,26 @@ class TagsController < ApplicationController
def show
@tag = Tag.find_by!(name: params[:id].downcase)
@statuses = @tag.nil? ? [] : Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id])
@statuses = Status.as_tag_timeline(@tag, current_account, params[:local]).paginate_by_max_id(20, params[:max_id])
@statuses = cache_collection(@statuses, Status)
respond_to do |format|
format.html
format.json do
render json: collection_presenter, serializer: ActivityPub::CollectionSerializer, adapter: ActivityPub::Adapter
end
end
end
private
def collection_presenter
ActivityPub::CollectionPresenter.new(
id: tag_url(@tag),
type: :ordered,
size: @tag.statuses.count,
items: @statuses.map { |s| ActivityPub::TagManager.instance.uri_for(s) }
)
end
end

View File

@@ -2,6 +2,8 @@
module WellKnown
class HostMetaController < ApplicationController
include RoutingHelper
def show
@webfinger_template = "#{webfinger_url}?resource={uri}"

View File

@@ -2,6 +2,8 @@
module WellKnown
class WebfingerController < ApplicationController
include RoutingHelper
def show
@account = Account.find_local!(username_from_resource)
@canonical_account_uri = @account.to_webfinger_s

View File

@@ -1,8 +0,0 @@
# frozen_string_literal: true
module Activitystreams2BuilderHelper
# Gets a usable name for an account, using display name or username.
def account_name(account)
account.display_name.presence || account.username
end
end

Some files were not shown because too many files have changed in this diff Show More