Compare commits

...

468 commits

Author SHA1 Message Date
Rafael Caricio 02d2270d81
Hack: Allow for me specifically to migrate to GoToSocial 2023-08-07 19:06:21 +02:00
Rafael Caricio 120510ccbf
No need for published field to be strictly present 2023-08-07 19:05:21 +02:00
kim 9a291dea84
[performance] add caching of status fave, boost of, in reply to ID lists (#2060) 2023-08-04 12:28:33 +01:00
kim 00adf18c24
[feature] simpler cache size configuration (#2051)
* add automatic cache max size generation based on ratios of a singular fixed memory target

Signed-off-by: kim <grufwub@gmail.com>

* remove now-unused cache max-size config variables

Signed-off-by: kim <grufwub@gmail.com>

* slight ratio tweak

Signed-off-by: kim <grufwub@gmail.com>

* remove unused visibility config var

Signed-off-by: kim <grufwub@gmail.com>

* add secret little ratio config trick

Signed-off-by: kim <grufwub@gmail.com>

* fixed a word

Signed-off-by: kim <grufwub@gmail.com>

* update cache library to remove use of TTL in result caches + slice cache

Signed-off-by: kim <grufwub@gmail.com>

* update other cache usages to use correct interface

Signed-off-by: kim <grufwub@gmail.com>

* update example config to explain the cache memory target

Signed-off-by: kim <grufwub@gmail.com>

* update env parsing test with new config values

Signed-off-by: kim <grufwub@gmail.com>

* do some ratio twiddling

Signed-off-by: kim <grufwub@gmail.com>

* add missing header

* update envparsing with latest defaults

Signed-off-by: kim <grufwub@gmail.com>

* update size calculations to take into account result cache, simple cache and extra map overheads

Signed-off-by: kim <grufwub@gmail.com>

* tweak the ratios some more

Signed-off-by: kim <grufwub@gmail.com>

* more nan rampaging

Signed-off-by: kim <grufwub@gmail.com>

* fix envparsing script

Signed-off-by: kim <grufwub@gmail.com>

* update cache library, add sweep function to keep caches trim

Signed-off-by: kim <grufwub@gmail.com>

* sweep caches once a minute

Signed-off-by: kim <grufwub@gmail.com>

* add a regular job to sweep caches and keep under 80% utilisation

Signed-off-by: kim <grufwub@gmail.com>

* remove dead code

Signed-off-by: kim <grufwub@gmail.com>

* add new size library used to libraries section of readme

Signed-off-by: kim <grufwub@gmail.com>

* add better explanations for the mem-ratio numbers

Signed-off-by: kim <grufwub@gmail.com>

* update go-cache

Signed-off-by: kim <grufwub@gmail.com>

* library version bump

Signed-off-by: kim <grufwub@gmail.com>

* update cache.result{} size model estimation

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-08-03 11:34:35 +02:00
tobi e8a20f587c
[bugfix] Rework MultiError to wrap + unwrap errors properly (#2057)
* rework multierror a bit

* test multierror
2023-08-02 17:21:46 +02:00
kim 2cee8f2dd8
[bugfix] fix slow accounts / statuses using emojis lookups (#2056)
* update DeleteEmoji to use faster relational tables for status / account finding

Signed-off-by: kim <grufwub@gmail.com>

* update Get{Accounts,Statuses}UsingEmoji() to also use relational tables

Signed-off-by: kim <grufwub@gmail.com>

* remove the now unneeded tags relation from newStatusQ()

Signed-off-by: kim <grufwub@gmail.com>

* fix table names

Signed-off-by: kim <grufwub@gmail.com>

* fix account and status selects using emojis

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-08-02 16:11:23 +02:00
kim 24516b84c2
[bugfix] handle HEAD requests more elegantly (#2055)
Signed-off-by: kim <grufwub@gmail.com>
2023-08-02 10:28:20 +02:00
tobi cec29e2a8d
[bugfix] Allow instance accounts to be shown in search results in certain circumstances (#2053) 2023-08-02 08:31:09 +01:00
tobi 2be83fdca5
[feature] Allow users to skip http client tls verification for testing purposes (with appropriately loud warnings) (#2052) 2023-08-01 18:50:17 +01:00
tobi 9bd03e122e
[feature] Set timezone in Docker using TZ env variable (#2050) 2023-08-01 14:47:53 +02:00
tobi 70929c1691
Revert "[feature] Configurable timezone in containers (#2046)" (#2048)
This reverts commit 96dd0e75f2.
2023-08-01 12:31:50 +02:00
Charles Chin 96dd0e75f2
[feature] Configurable timezone in containers (#2046) 2023-08-01 12:09:46 +02:00
tobi 2796a2e82f
[feature] Hashtag federation (in/out), hashtag client API endpoints (#2032)
* update go-fed

* do the things

* remove unused columns from tags

* update to latest lingo from main

* further tag shenanigans

* serve stub page at tag endpoint

* we did it lads

* tests, oh tests, ohhh tests, oh tests (doo doo doo doo)

* swagger docs

* document hashtag usage + federation

* instanceGet

* don't bother parsing tag href

* rename whereStartsWith -> whereStartsLike

* remove GetOrCreateTag

* dont cache status tag timelineability
2023-07-31 15:47:35 +02:00
kim ed2477ebea
[performance] cache follow, follow request and block ID lists (#2027) 2023-07-31 11:25:29 +01:00
tobi de148e9f9f
[bugfix/frontend] Decode URI component domain before showing on frontend (#2043) 2023-07-31 12:18:27 +02:00
dependabot[bot] a5a80b4bbe
[chore]: Bump github.com/abema/go-mp4 from 0.10.2-0.20230727031202-a1a707db6ecd to 0.11.0 (#2042)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 09:47:56 +01:00
dependabot[bot] 9ed9d96597
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.60 to 7.0.61 (#2041)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-31 09:47:25 +01:00
Vyr Cossont b874e9251e
[feature] Implement markers API (#1989)
* Implement markers API

Fixes #1856

* Correct import grouping in markers files

* Regenerate Swagger for markers API

* Shorten names for readability

* Cache markers for 6 hours

* Update DB ref

* Update envparsing.sh
2023-07-29 12:49:14 +02:00
tobi cf4bd700fb
[chore] Update activity dependency (#2031) 2023-07-27 20:54:30 +02:00
tobi e747c14685
[chore] fix merge issue (#2029) 2023-07-27 12:54:27 +02:00
Dominik Süß 98c2b8ff7e
[chore] update go-mp4 to latest commit (#2028)
This adds support for probing mp4 files with a co64 box instead of an stco box,
which is the case for videos recorded on newer android devices.
2023-07-27 10:31:36 +02:00
Vyr Cossont 22ac4607a1
[feature] Support setting private notes on accounts (#1982)
* Support setting private notes on accounts

* Reformat comment whitespace

* Add missing license headers

* Use apiutil.ParseID

* Rename Note model and cache to AccountNote

* Update golden cache config in test/envparsing.sh

* Rename gtsmodel/note.go to gtsmodel/accountnote.go

* Update AccountNote uniqueness constraint name

Now has same prefix as other indexes on this table.

---------

Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
2023-07-27 10:30:39 +02:00
kim 5f3e095717
[performance] retry db queries on busy errors (#2025)
* catch SQLITE_BUSY errors, wrap bun.DB to use our own busy retrier, remove unnecessary db.Error type

Signed-off-by: kim <grufwub@gmail.com>

* remove dead code

Signed-off-by: kim <grufwub@gmail.com>

* remove more dead code, add missing error arguments

Signed-off-by: kim <grufwub@gmail.com>

* update sqlite to use maxOpenConns()

Signed-off-by: kim <grufwub@gmail.com>

* add uncommitted changes

Signed-off-by: kim <grufwub@gmail.com>

* use direct calls-through for the ConnIface to make sure we don't double query hook

Signed-off-by: kim <grufwub@gmail.com>

* expose underlying bun.DB better

Signed-off-by: kim <grufwub@gmail.com>

* retry on the correct busy error

Signed-off-by: kim <grufwub@gmail.com>

* use longer possible maxRetries for db retry-backoff

Signed-off-by: kim <grufwub@gmail.com>

* remove the note regarding max-open-conns only applying to postgres

Signed-off-by: kim <grufwub@gmail.com>

* improved code commenting

Signed-off-by: kim <grufwub@gmail.com>

* remove unnecessary infof call (just use info)

Signed-off-by: kim <grufwub@gmail.com>

* rename DBConn to WrappedDB to better follow sql package name conventions

Signed-off-by: kim <grufwub@gmail.com>

* update test error string checks

Signed-off-by: kim <grufwub@gmail.com>

* shush linter

Signed-off-by: kim <grufwub@gmail.com>

* update backoff logic to be more transparent

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-07-25 10:34:05 +02:00
kim 9eff0d46e4
[feature/performance] support uncaching remote emoji + scheduled cleanup functions (#1987) 2023-07-24 13:14:13 +01:00
dependabot[bot] 81fe59dadc
[chore]: Bump github.com/microcosm-cc/bluemonday from 1.0.24 to 1.0.25 (#2021) 2023-07-24 10:24:03 +00:00
dependabot[bot] b05f6c8f56
[chore]: Bump github.com/yuin/goldmark from 1.5.4 to 1.5.5 (#2023) 2023-07-24 10:21:14 +00:00
dependabot[bot] c9f3539b5a
[chore]: Bump codeberg.org/gruf/go-cache/v3 from 3.4.1 to 3.4.3 (#2022) 2023-07-24 10:20:11 +00:00
dependabot[bot] 8b71567f9e
[chore]: Bump github.com/jackc/pgconn from 1.14.0 to 1.14.1 (#2024) 2023-07-24 10:14:16 +00:00
dependabot[bot] b7891bb462
[chore]: Bump go.uber.org/automaxprocs from 1.5.2 to 1.5.3 (#2020) 2023-07-24 10:13:31 +00:00
Daenney 994d5e80d9
[chore] Disable the right webfinger test (#2018)
We don't talk about 8868889 / #1983.
2023-07-23 16:33:16 +02:00
tobi 5a29a031ad
[chore] Admin CLI + new account creation refactoring (#2008)
* set maxPasswordLength to 72 bytes, rename validate function

* refactor NewSignup

* refactor admin account CLI commands

* refactor oidc create user

* refactor processor create

* tweak password change, check old != new password
2023-07-23 12:33:17 +02:00
Daenney f8f0312042
[feature] Report Masto version in /api/v1/instance (#1977) 2023-07-21 18:49:13 +01:00
dependabot[bot] 43a2753ef0
[chore]: Bump modernc.org/sqlite from 1.23.1 to 1.24.0 (#1993)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.23.1 to 1.24.0.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.23.1...v1.24.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-21 16:43:56 +02:00
Daenney da8282081c
[feature] Lower remote media cache config duration (#2007)
The old default of 30d can lead to a lot of media getting cached and
significant disk usage, even on small or single person instances. A lot
of deployments decrease this value, to 15 or even less. This is less of
an issue when using object storage, but for local storage which is the
more popular deployment option running out of disk space is unpleasant.

With GoToSocial's aim to fit in small places, this changes the default
to a much more conservative 7 days. In all likelihood people aren't
scrolling that far back in their timeline so this change shouldn't
result in any issue. Existing deployments will only be affected by
this change if the admin hasn't already configured this value, or didn't
bootstrap from the example configuration.
2023-07-21 16:22:59 +02:00
dependabot[bot] fa57c699fe
[chore]: Bump github.com/jackc/pgx/v5 from 5.4.1 to 5.4.2 (#1991) 2023-07-21 14:22:20 +00:00
dependabot[bot] 83139989b5
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.59 to 7.0.60 (#1992) 2023-07-21 14:22:17 +00:00
dependabot[bot] d53449ccb4
[chore]: Bump github.com/go-playground/form/v4 from 4.2.0 to 4.2.1 (#1994) 2023-07-21 14:22:13 +00:00
dependabot[bot] 8ac3a3f688
Bump word-wrap from 1.2.3 to 1.2.4 in /web/source (#2001) 2023-07-21 14:21:50 +00:00
tobi 89ee9d5004
[bugfix] Return all accounts when list accounts limit <= 0 (#2014) 2023-07-21 13:56:38 +01:00
tobi d6fa74e5dc
[bugfix] Change maximumPasswordLength to 72 bytes (#2012) 2023-07-21 10:29:18 +01:00
mirabilos 95e2024c2a
[docs] Apache setup for Caching assets and media (#2005) (#2005)
Also change the nginx fileserver expiry, after discussion, to
one week, to match.
2023-07-20 18:48:52 +02:00
kim f4319740ab
[bugfix] more robust list timeline invalidation (#1995) 2023-07-18 09:43:17 +01:00
tobi 346ecabd07
[bugfix] Add missing continue statement in prepareXBetweenIDs (#1996) 2023-07-18 09:39:16 +01:00
tobi 12b6cdcd8c
[bugfix] Set Vary header correctly on cache-control (#1988)
* [bugfix] Set Vary header correctly on cache-control

* Prefer activitypub types on AP endpoints

* use immutable on file server, vary by range

* vary auth on Accept
2023-07-13 21:27:25 +02:00
Daenney 88688899aa
[chore] Skip webfinger test on CI (#1983) 2023-07-12 16:09:49 +01:00
tobi 1951e6c840
[bugfix] Update account Update logic (#1984) 2023-07-12 12:20:15 +01:00
firescry 8d92b2479f
[bugfix] Align default values in the configuration file with the code (#1971)
* Set default value of SMTPFrom to empty string

This parameter should contain proper e-mail address (to be provided by user during configuration).

* Update default values in example/config.yaml

Default values and related comments in example/config.yaml are aligned
with values defined in internal/config/defaults.go.
Small improvements to foramting of config.yaml file.

* Add default value for AdvancedThrottlingRetryAfter to internal/config/defaults.go

AdvancedThrottlingRetryAfter was introduced in 70739d3 (superseriousbusiness/gotosocial#1466).

* Update config.yaml snippets in documentation
2023-07-12 10:28:41 +02:00
dependabot[bot] f5d6503aad
Bump semver from 6.3.0 to 6.3.1 in /web/source (#1981)
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-12 10:27:31 +02:00
MaeIsBad 0d267fd598
[bugfix] Properly handle range > content-length (#1979)
This makes the serveFileRange function return the entire file
if suffix-range is larger than content-length in compliance with RFC9110

Co-authored-by: mae <git@badat.dev>
2023-07-12 09:51:51 +02:00
tobi ca5492b65f
[bugfix] Tidy up rss feed serving; don't error on empty feed (#1970)
* [bugfix] Tidy up rss feed serving; don't error on empty feed

* fall back to account creation time as rss feed update time

* return feed early when account has no eligible statuses
2023-07-10 17:05:59 +02:00
dependabot[bot] a29b5affc8
[chore]: Bump golang.org/x/oauth2 from 0.9.0 to 0.10.0 (#1975)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 12:58:06 +01:00
Daenney f0dad439f6
[feature] Use Read/Write lock for config (#1969) 2023-07-10 12:56:14 +01:00
dependabot[bot] 6de5ca46f8
[chore]: Bump golang.org/x/net from 0.11.0 to 0.12.0 (#1973)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 12:43:32 +01:00
dependabot[bot] 901770f5c7
[chore]: Bump golang.org/x/image from 0.8.0 to 0.9.0 (#1972)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-10 12:31:09 +01:00
Daenney 65c89709bc
[chore] Fix password typos (#1966)
Fixes #1963
2023-07-09 18:25:37 +02:00
Daenney b0f0c8b822
[docs] Activate the edit feature (#1967)
We already set edit_uri, but we forgot to enable the feature flag. By
turning it on each page now gets an edit button on the right hand side
of the page header. This'll open the edit view in GitHub.
2023-07-09 18:25:14 +02:00
tobi 6dbb8ba7aa
[bugfix] Fix delete follow req instead of follow (#1962) 2023-07-08 23:12:06 +02:00
tobi f40bb02f31
[bugfix] Delete mutual follow (requests) when receiving block from remote (#1960)
* [bugfix] Delete mutual follow (requests) on block

* fix test
2023-07-08 16:43:12 +02:00
Daenney 747ea584bd
[docs] Clarify how to add a page (#1959)
* Add instructions on how to make a new page show up in the sidebar / navigation
* Explain how to create a virtual env to install the dependencies in if you're not using Conda
2023-07-08 15:44:58 +02:00
Daenney 672386a1b9
[bugfix] Don't overflow on very wide status'es (#1956)
If someone makes a post with a long, uninterrupted piece of text in a
code snippet, we would stretch the column to fit it, resulting in the
UI going a bit whacky.

By setting min-width: 0% this fixes it, and we now automatically get a
scrollbar on overflow instead.

Fixes: #1952
2023-07-08 09:54:26 +02:00
tobi 2a99df0588
[feature] enable + document explicit IP dialer allowing/denying (#1950)
* [feature] enable + document explicit IP dialer allowing/denying

* lord have mercy

* allee jonge

* shortcut check ipv6 prefixes

* comment

* separate httpclient_test, export Sanitizer
2023-07-07 16:17:39 +02:00
tobi ac564c1862
[bugfix] Reorder web view logic, other small fixes (#1954) 2023-07-07 14:58:53 +02:00
Daenney 9ff4c20374
[docs] Rework backups a bit (#1942)
* [docs] Rework backups a bit

This changes the existing backup documentation to:

* Push a bit harder on people to perform backups, it's not really just a
  nice to have
* Removes the language about migrating to/from GoToSocial and a
  different ActivityPub server since that's really not supported
* Adds a section about using backup software and provides an example on
  how to do this using Borgmatic

* [docs] Remove too much info in db section

* [docs] Add docs on how to backup local media

This adds documentation pointing people at the media list-local command
in order to determine what media files they need to include as part of
their backups.

Provides a Python script that people can use to transform the media
listing from the CLI into Borg patterns. It also includes a Borgmatic
config.yaml in the repository so people can easily fetch it instead of
copy-pasting from the docs.

* [bugfix] Ensure we emit an absolute path prefix

It works either way, as a pattern like data/files/<ID> would match a
file on /data/files/<ID>. But it would potentially also match any path
that happens to include data/files/<ID> but not rooted at the
storage-local-base-path.

* [docs] Add more links to media list CLI reference
2023-07-07 11:45:42 +02:00
Daenney 81f33c3b9f
[feature] Add media list command (#1943)
* [feature] Add media list command

This is an attempt to help alleviate #1776. Using admin media list
--local the full path to each local media file will be printed, with a
newline. The output of this should be feadable into backup tools in
order to allow to backup local media too. Together with the database
this should allow to fully recover from the loss of an instance.

The list command also gets a --remote flag for symmetry. In the case
of --remote we print the RemoteURL instead, the location the asset can
be retrieved from.

To get all media, you can run with --local and --remote.

* [bugfix] Fix the test failures

* [feature] Reimplement list media as top commands

This changes the implementation of admin media list --<variant> to two
separate top-level commands, list-local and list-remote.

The implementation now iterates over over the database in batches of 200
in order to avoid loading all media metadata into memory.

* [feature] Implement ListMedia with filter callback

This does away with the somewhat odd iterator-like structure we had
before and does away with most of the loop duplication in list-local and
list-remote. Instead they call GetAllMediaPaths with a filter func to
select the media they want. That's accumulated into a slice and
eventually returned.

* [bugfix] Simplify remote filter

Since we don't append the empty string anywhere, the remote filter can
be limited to returning RemoteURL, as that'll be an empty string for
local media.

* [docs] Add media list commands to CLI reference

---------

Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
2023-07-07 11:35:05 +02:00
tobi e70bf8a6c8
[chore/bugfix] Domain block tidying up, Implement first pass of 207 Multi-Status (#1886)
* [chore/refactor] update domain block processing

* expose domain block import errors a lil better

* move/remove unused query keys
2023-07-07 11:34:12 +02:00
tobi d9c69f6ce0
[chore/performance] Remove remaining 'whereEmptyOrNull' funcs (#1946) 2023-07-05 12:34:37 +02:00
tobi 3d16962173
[chore/bugfix] Break Websockets logic into smaller read/write functions, don't log expected errors (#1932)
* [chore/bugfix] Break Websockets logic into smaller read/write functions, don't log expected errors

* tweak

* tidy up, use control message
2023-07-04 12:55:10 +02:00
Daenney ba0bc06b8c
[feature] Add instance stats to /about (#1936)
When you configure the landing-page-user redirect, you lose access to
the one page that displays server stats. This adds the same stats as we
have on / to /about to bring those back.
2023-07-04 11:33:07 +02:00
dependabot[bot] 1218f97e01
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.58 to 7.0.59 (#1941)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.58 to 7.0.59.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.58...v7.0.59)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 11:22:40 +02:00
Daenney 2a40c81f10
[bugfix] Try to fix the webfinger test, again (#1931)
For some reason we hit the case in CI where the
TestFingerWithHostMetaCacheStrategy seems to experience some time
dilation. It's possible this is a genuine bug, but I can't for the life
of me reproduce it locally, even after having run this test thousands of
times (-count=1000 when invoking go test etc.)

This changes the test to explicitly stop the webfinger cache, set TTL
and Sweep frequency to something well beyond the lifetime of the cache
during the test and then starts the cache again. Hopefully that does it,
because the other option that remains is that for some reason
timekeeping in CI/Docker is not as precise as when running the test on a
host.
2023-06-27 18:32:03 +02:00
tobi d98b6318ac
[bugfix] Use gtserror package for WrongType errs (#1930)
* [bugfix] Use gtserror package for WrongType errs

* test
2023-06-27 11:37:42 +02:00
dependabot[bot] e3e0f673cc
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.56 to 7.0.58 (#1928) 2023-06-26 20:45:49 +00:00
dependabot[bot] 4ad933b71c
[chore]: Bump github.com/miekg/dns from 1.1.54 to 1.1.55 (#1929)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.54 to 1.1.55.
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.54...v1.1.55)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-26 22:35:40 +02:00
dependabot[bot] 120743d3bf
[chore]: Bump github.com/tdewolff/minify/v2 from 2.12.6 to 2.12.7 (#1927) 2023-06-26 09:34:00 +00:00
dependabot[bot] 33ccb716fc
[chore]: Bump golang.org/x/image from 0.7.0 to 0.8.0 (#1926) 2023-06-26 09:32:58 +00:00
tobi 52ebff5e7e
[bugfix] Only mark status orphaned on 410 Gone (#1923) 2023-06-24 13:59:28 +02:00
tobi 3e19f480e6
[bugfix] Ensure InReplyToID set properly, update dereference ancestors func (#1921) 2023-06-24 08:32:10 +01:00
kim 9a22102fa8
[bugfix/chore] oauth entropy fix + media cleanup tasks rewrite (#1853) 2023-06-22 20:46:36 +01:00
Daenney c4cf6326d8
[docs] Clarify email requirement for OIDC (#1918) 2023-06-21 21:22:51 +02:00
kim 8e0043104d
[performance] update go-cache library (#1917)
* update go-cache library

Signed-off-by: kim <grufwub@gmail.com>

* fix broken test after cache library upgrade

Signed-off-by: kim <grufwub@gmail.com>

* fix the webfinger test

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-06-21 21:08:48 +02:00
tobi 831ae09f8b
[feature] Add partial text search for accounts + statuses (#1836) 2023-06-21 17:26:40 +01:00
tobi fab64a20b0
[docs] Disambiguate docker version, don't recommend opening localhost (#1913) 2023-06-20 14:36:23 +02:00
dependabot[bot] f56dd290e1
[chore]: Bump golang.org/x/oauth2 from 0.8.0 to 0.9.0 (#1908) 2023-06-19 08:19:49 +00:00
Umar Getagazov 84eb7eaf26
[chore] Fix Swagger paths for lists API endpoints (#1904) 2023-06-19 10:00:19 +02:00
Umar Getagazov 73bfb5fbff
[bugfix] Parse POST-style forms in the list member removal endpoint (#1903) 2023-06-19 09:58:58 +02:00
dependabot[bot] 70357a770f
[chore]: Bump github.com/jackc/pgx/v5 from 5.3.1 to 5.4.1 (#1907)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.3.1 to 5.4.1.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.3.1...v5.4.1)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 09:56:15 +02:00
dependabot[bot] b560fe186d
[chore]: Bump golang.org/x/net from 0.10.0 to 0.11.0 (#1909)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/net/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 09:54:50 +02:00
dependabot[bot] 54f3387c11
[chore]: Bump golang.org/x/crypto from 0.9.0 to 0.10.0 (#1910)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/crypto/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-19 09:54:29 +02:00
tobi d8e16a226a
[chore/bugfix] Refactor ap/extract.go functions, return URIs more reliably (#1897) 2023-06-17 16:49:11 +01:00
Umar Getagazov 0fa06c0cde
[bugfix] Accept non-multipart forms for account updates (#1896)
* [bugfix] Update Swagger schema per max_profile_fields addition

* [bugfix] Accept non-multipart forms for account updates
2023-06-16 11:16:04 +02:00
tobi 827cc4df56
[chore/bugfix] Demote failed inbox forwarding to warn log rather than error return (#1892) 2023-06-14 15:08:31 +02:00
tobi 24fbdf2b0a
[chore] Refactor AP authentication, other small bits of tidying up (#1874) 2023-06-13 15:47:56 +01:00
Daenney 433b56d2f9
[docs] Add certificates and firewalling to advanced (#1888)
* [docs] Add a certificates guide in Advanced

This adds some documentation about the process of getting certificates
through ACME in general. It also provides a number of links to
alternative clients and certbot deployment guides that are up to date.

Slightly restructure the NGINX and Apache reverse proxy documentation
and insert mentions to the Provisioning TLS certificates advanced
documentation in them.

* [docs] Add firewall section in Advanced

* [docs] Add new guides to section indexes

* [docs] Fix spelling issue

* [docs] Fix a few typos
2023-06-13 16:30:09 +02:00
f0x52 8fb5a7e7f8
[Frontend] Settings for profile fields (#1885)
* get max emoji size from instance settings

* expose (hardcoded) max amount of profile fields in instance api

* basic profile field setting

* fix profile field hook structure for updates

* *twirls mustache* fix ze tests

---------

Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-06-13 12:21:26 +02:00
Daenney 4990099fde
[docs] Made Advanced its own section (#1883)
* [docs] Made Advanced its own section

This splits the Advanced page off from the Getting Started guide and
makes it its own thing. It now has some additional sub-sections for
bigger topics like caching and enhanced security. This also moves
tracing from Getting Started to Advanced as that feels like a more
appropriate location for it.

The enhanced security looks a little silly with a single section, but I
have guides pending for firewall configurations and I'd also like to
consolidate our how to provision TLS certificates in there as we repeat
this information multiple times.

* [docs] Fix all my spelling errors

* [docs] Inline the links in sandboxing
2023-06-12 15:38:53 +02:00
dependabot[bot] 5d19fb1b2f
[chore]: Bump modernc.org/sqlite from 1.23.0 to 1.23.1 (#1884)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.23.0 to 1.23.1.
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.23.0...v1.23.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-12 11:25:23 +02:00
tobi 5e2897e35c
[bugfix] Invalidate timeline entries for status when stats change (#1879) 2023-06-11 10:18:44 +01:00
Daenney 84e1c7a7c4
[docs] Revamp the installation guide (#1877)
This tries to revamp/restructure the installation guide. It's renamed to
"Getting Started" as it now contains a few more things than just the
installation, especially the deployment considerations which we didn't
use to spell out as much ahead of time.

Installation is now a section with the guides on their own. I've removed
a bit of redundancy like the user creation. I also removed the rogue
reverse proxy section in the Docker guide and lifted that into the
reverse proxy section.
2023-06-10 11:13:04 +02:00
tobi b0015a3604
[bugfix] Delete from list timeline on status deletion (#1878) 2023-06-10 11:11:54 +02:00
Daenney 6f6b8576f0
[docs] Add example tracing infrastructure (#1866)
This adds an example on how to get Grafana Tempo up to receive spans as
well as Grafana itself to view them.

I've added this as a separate Tracing doc in the installation guide as
the Advanced one was starting to get rather full.

Fixes: #1791
2023-06-09 16:04:23 +02:00
tobi b401bd1ccb
[chore] update latest deps, ensure readme up to date (#1873)
* [chore] update latest deps, ensure readme up to date

* remove double entry
2023-06-05 10:15:05 +02:00
dependabot[bot] f1b70cc00f
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.55 to 7.0.56 (#1869)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.55 to 7.0.56.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.55...v7.0.56)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-05 09:28:13 +02:00
dependabot[bot] 7638a68688
[chore]: Bump github.com/stretchr/testify from 1.8.3 to 1.8.4 (#1872)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.3 to 1.8.4.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.3...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-05 09:25:52 +02:00
tobi d7d660374a
[bugfix] Fix slow joined home timeline query (#1867) 2023-06-04 20:17:28 +01:00
Daenney 45773a0bf4
[bugfix/docs] AppArmor profile for SQLite (#1864)
Our default configuration places the SQLite DB in /gotosocial/, but the
AppArmor profile doesn't allow us to write there. Instead of making the
whole directory writable, add a writable area in /gotosocial/db/ instead
and advise in the docs to move the DB there.
2023-06-04 18:55:57 +02:00
tobi 97bc2e713a
[chore] tidy + test timelines a bit better (#1865)
* [chore] tidy + test timelines a bit better

* thanks linter
2023-06-04 18:55:30 +02:00
Daenney 186e849dbf
[docs] Add Repology stats (#1859)
Instead of a manually curated list of distribution packages, this adds
the Repology[1] widget instead.

This also separates out the distribution packages from the
self-hosting/deployment options into their own sections.

[1]: https://repology.org/project/gotosocial/versions
2023-06-04 11:40:32 +02:00
tobi 21c1552daa
[chore] Update versions, fix lint errors (#1860) 2023-06-03 13:58:57 +02:00
tobi 1d4137fb88
[bugfix] Fix first item of thread dereferencing always being skipped (#1858)
* [bugfix] Fix first item of thread dereferencing always being skipped

* tweak to status descendant item iteration

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: kim <grufwub@gmail.com>
2023-06-03 11:35:15 +02:00
Julian-Samuel Gebühr 1f39275c0f
[bugfix] Allow lowercase emoji shortcode in frontend (#1851)
* Replace pinafore with semaphore

* Typo

* Allow lowercase emoji shortcode in frontend

* Fix failing test (corrected expected outcome)
2023-06-02 17:42:14 +02:00
tobi 2358cf4e43
[bugfix] Overwrite API client closed errors with 499 - Client Closed Request (#1857)
* [bugfix] Overwrite client closed errors with 499

* bleep bloop

* review changes
2023-06-02 15:19:43 +02:00
kim 20978b1278
[performance] wrap httpclient response body to ensure drained before close (#1854)
Signed-off-by: kim <grufwub@gmail.com>
2023-06-02 10:34:52 +02:00
dependabot[bot] 55aacaf4b0
[chore]: Bump github.com/gin-gonic/gin from 1.9.0 to 1.9.1 (#1855)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-01 22:20:16 +01:00
tobi 23705b31e4
[chore/frontend] refactor header templating, add apple-touch-icon (#1850) 2023-05-31 13:54:00 +02:00
kim 9da20eeecb
[bugfix] only attempt to populate account/statuses from DB if already exist (#1839)
* only attempt to populate account/statuses from DB if already up-to-date

Signed-off-by: kim <grufwub@gmail.com>

* add missing status is-up-to-date check :grimace: + ensure populated if so

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-31 10:39:54 +02:00
tobi 36fcd2e604
[docs] clarify other federation modes not yet implemented (#1849) 2023-05-31 10:35:55 +02:00
Julian-Samuel Gebühr 70262d403c
[fix] Fix link to remote emoji pgae (#1845)
* Replace pinafore with semaphore

* Typo

* Fix remote emoji link
2023-05-31 10:23:14 +02:00
dependabot[bot] 049b02aab1
[chore]: Bump github.com/microcosm-cc/bluemonday from 1.0.23 to 1.0.24 (#1843)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 14:03:08 +01:00
dependabot[bot] f620ee8da9
[chore]: Bump github.com/coreos/go-oidc/v3 from 3.5.0 to 3.6.0 (#1840)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 13:55:51 +01:00
dependabot[bot] e50b228539
[chore]: Bump github.com/ulule/limiter/v3 from 3.11.1 to 3.11.2 (#1841)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 13:54:05 +01:00
dependabot[bot] 2e7043be95
[chore]: Bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#1842)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 13:47:57 +01:00
dependabot[bot] 9ed96bc570
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.53 to 7.0.55 (#1844)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-29 13:47:11 +01:00
tobi 46d4ec0f05
[bugfix/chore] Inbox post updates (#1821)
Co-authored-by: kim <grufwub@gmail.com>
2023-05-28 20:05:15 +01:00
kim 5faeb4de20
[chore] tidy up media manager, add calling func to errors, build-script improvements (#1835)
* media manager tidy-up: de-interface and remove unused PostDataFunc

Signed-off-by: kim <grufwub@gmail.com>

* remove last traces of media.Manager being an interface

Signed-off-by: kim <grufwub@gmail.com>

* update error to provide caller, allow tuneable via build tags

Signed-off-by: kim <grufwub@gmail.com>

* remove kim-specific build script changes

Signed-off-by: kim <grufwub@gmail.com>

* fix merge conflicts

Signed-off-by: kim <grufwub@gmail.com>

* update build-script to support externally setting build variables

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-28 14:08:35 +02:00
tobi 1f06914007
[docs] Update + simplify roadmap, revise beta estimate (#1826) 2023-05-26 18:00:30 +02:00
decentral1se 681486f84f
[docs]: semaphone ref & DEBUG usage for standalone testing (#1828)
* Point to semaphore for local testing
* Use `DEBUG=1` when running the testrig
* Provide an approach for install yarn

Co-authored-by: decentral1se <cellarspoon@riseup.net>
2023-05-25 18:39:00 +02:00
Daenney e0962987aa
[bugfix/docs] Fix clear notifications API docs (#1831)
The handler is already hooked to the right path, it's just the docs that
were missing the path.
2023-05-25 16:56:33 +02:00
tobi fc524f8cf1
[feature] Configurable custom css length (#1827)
* [feature] Make accounts custom css length configurable

* test custom css validation
2023-05-25 15:18:15 +02:00
decentral1se 45f961a9fe
[bugfix] allow usernames of length 1 (#1823)
Closes https://github.com/superseriousbusiness/gotosocial/issues/1691.

Co-authored-by: decentral1se <cellarspoon@riseup.net>
2023-05-25 11:15:10 +02:00
tobi f5c004d67d
[feature] Add List functionality (#1802)
* start working on lists

* further list work

* test list db functions nicely

* more work on lists

* peepoopeepoo

* poke

* start list timeline func

* we're getting there lads

* couldn't be me working on stuff... could it?

* hook up handlers

* fiddling

* weeee

* woah

* screaming, pissing

* fix streaming being a whiny baby

* lint, small test fix, swagger

* tidying up, testing

* fucked! by the linter

* move timelines to state like a boss

* add timeline start to tests using state

* invalidate lists
2023-05-25 10:37:38 +02:00
decentral1se 282be6f26d
[docs] local docs hacking howto (#1816)
Co-authored-by: decentral1se <cellarspoon@riseup.net>
2023-05-23 17:38:39 +02:00
decentral1se d0e747cd58
[docs] code highlighting configuration (#1817)
Co-authored-by: decentral1se <cellarspoon@riseup.net>
2023-05-23 17:04:00 +02:00
decentral1se 999a6ae437
[docs] support copy/pasta for code blocks (#1818)
Co-authored-by: decentral1se <cellarspoon@riseup.net>
2023-05-23 11:51:43 +02:00
dependabot[bot] a0952adc40
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.52 to 7.0.53 (#1808)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.52 to 7.0.53.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.52...v7.0.53)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-22 20:05:27 +02:00
tobi c48abd8bc0
[chore] update account statuses paging logic (#1814) 2023-05-22 16:32:36 +02:00
dependabot[bot] ea1bbacf4b
[chore]: Bump github.com/go-playground/validator/v10 (#1812)
Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.13.0 to 10.14.0.
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.13.0...v10.14.0)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-22 09:17:48 +02:00
Julian-Samuel Gebühr 9c24dee01f
[chore] Replace pinafore with semaphore (#1801)
* Replace pinafore with semaphore

* Typo
2023-05-21 22:40:43 +02:00
kim 2063d01cdb
[bugfix] Add back removed ValidateRequest() before backoff-retry loop (#1805)
* add back removed ValidateRequest() before backoff-retry loop

Signed-off-by: kim <grufwub@gmail.com>

* include response body in error response log

Signed-off-by: kim <grufwub@gmail.com>

* improved error response body draining

Signed-off-by: kim <grufwub@gmail.com>

* add more code commenting

Signed-off-by: kim <grufwub@gmail.com>

* move new error response logic to gtserror, handle instead in transport.Transport{} impl

Signed-off-by: kim <grufwub@gmail.com>

* appease ye oh mighty linter

Signed-off-by: kim <grufwub@gmail.com>

* fix mockhttpclient not setting request in http response

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-21 18:59:14 +02:00
Daenney 107237c8e8
[feature] Make client IP logging configurable (#1799) 2023-05-21 16:12:47 +01:00
tobi 68e54cbaa4
[bugfix] Start + stop caches properly for testrig + pruning (#1804)
* [bugfix] Start + stop caches properly for testrig + pruning

* go fmt ./...
2023-05-21 14:44:10 +02:00
tobi 99ddaba57e
[bugfix] Fix incorrect default for empty emoji domain (#1803) 2023-05-21 13:45:24 +02:00
Daenney c7702c47bb
[chore] Change time comparison in webfinger test (#1798)
Every now and then the TestFingerWithHostMetaCacheStrategy would fail on
a time related error. I suspect suite.Equal doesn't quite work as
expected when given two time.Time's, so instead explicitly check with
the time.Equal.
2023-05-16 15:09:29 +02:00
Daenney e91cabb704
[bugfix] Fix NegotiateFormat with multiple accept headers (#1797)
* [bugfix] Fix NegotiateAccept with multi accept

There's a bug in Gin's NegotiateFormat that doesn't handle the presence
of multilpe accept headers. This lifts the code from the PR @tsmethurst
sent a year ago to Gin into our codebase to fix the issue.

* [bugfix] Concat accept header in webfinger

Some implementations bug out when there's multiple accept headers,
including Gin (see 7050112af1ccc935ec542cb41fa8b07f7357539d). But things
seem to work reliably with a single accept header with multiple parts.

Fixes: #1793
2023-05-16 15:08:45 +02:00
Daenney 2478d83c84
[bugfix] Fix proxy_pass in named location (#1794)
A proxy_pass in a named location, @name, should not include a trailing
slash.
2023-05-15 19:53:42 +02:00
tobi 19dab83ee3
[docs] add missing observability settings to example config (#1790) 2023-05-15 14:17:04 +02:00
tobi 32aefd55b2
[docs] remove nginx trailing slash (#1789) 2023-05-15 14:07:19 +02:00
dependabot[bot] 89c1d583d0
[chore]: Bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#1784)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0.
- [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 12:52:50 +02:00
tobi 17b9a937b1
[bugfix] Fix duplicating fields on profile edit (#1788)
* [bugfix] Fix duplicating fields on profile edit

* test non-duplicate fields
2023-05-15 12:52:40 +02:00
dependabot[bot] e1b7ab2603
[chore]: Bump golang.org/x/oauth2 from 0.7.0 to 0.8.0 (#1785)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.7.0 to 0.8.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-15 12:23:08 +02:00
kim 2b7c815ed6
[bugfix] update go-cache to v3.3.3 (#1778)
* update go-cache to v3.3.1

Signed-off-by: kim <grufwub@gmail.com>

* bump go-cache again

Signed-off-by: kim <grufwub@gmail.com>

* remove accidentally comitted build-script changes

Signed-off-by: kim <grufwub@gmail.com>

* now v3.3.3 ...

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-14 15:17:03 +02:00
f0x52 514eb8c83e
[frogend/chore] Fix profile domain (#1779)
* render domain on profile pages

* remove unused additional sr-only spans
2023-05-14 14:49:01 +02:00
tobi 3046dabd50
[frogend/chore] Update backnextlinks (#1774) 2023-05-14 12:15:24 +02:00
tobi 1d8dec3998
[docs] Add implementation notes for report (Flag) functionality (#1324)
* add implementation notes for reports

* add note on Friendica
2023-05-13 15:01:41 +02:00
tobi 0e03507164
[docs] update instance splash and profile screenshots (#1775) 2023-05-13 12:58:07 +02:00
f0x52 89dcbd5a20
[frontend] Basic user moderation actions (#1728)
* remove info banner

* update swagger definition for AccountAction

* basic user view, suspend action

* clean up suspended user display

* basic user searching

* rename User -> Account for clarity

* refactor error boundary component to give better info

* appease the linter
2023-05-13 12:17:22 +02:00
tobi b47661f033
[bugfix] Downstep otel to fix freebsd compile issue (#1773)
https://github.com/open-telemetry/opentelemetry-go/issues/4076
2023-05-12 14:55:18 +02:00
tobi ec325fee14
[chore] Update a bunch of database dependencies (#1772)
* [chore] Update a bunch of database dependencies

* fix lil thing
2023-05-12 14:33:40 +02:00
f0x52 66df974143
[frogend/bugfix] fix dynamicSpoiler elements (#1771) 2023-05-12 13:50:37 +02:00
tobi b315aa10c8
[frogend/chore] remove break-all on profile fields (#1770) 2023-05-12 12:10:34 +02:00
tobi 8eda0051ec
[bugfix] Ensure account fields can be set by JSON (#1762) 2023-05-12 11:17:31 +02:00
kim 6c9d8e78eb
[feature] status refetch support (#1690)
* revamp http client to not limit requests, instead use sender worker

Signed-off-by: kim <grufwub@gmail.com>

* remove separate sender worker pool, spawn 2*GOMAXPROCS batch senders each time, no need for transport cache sweeping

Signed-off-by: kim <grufwub@gmail.com>

* improve batch senders to keep popping recipients until remote URL found

Signed-off-by: kim <grufwub@gmail.com>

* fix recipient looping issue

Signed-off-by: kim <grufwub@gmail.com>

* move request id ctx key to gtscontext, finish filling out more code comments, add basic support for not logging client IP

Signed-off-by: kim <grufwub@gmail.com>

* first draft of status refetching logic

Signed-off-by: kim <grufwub@gmail.com>

* fix testrig to use new federation alloc func signature

Signed-off-by: kim <grufwub@gmail.com>

* fix log format directive

Signed-off-by: kim <grufwub@gmail.com>

* add status fetched_at migration

Signed-off-by: kim <grufwub@gmail.com>

* remove unused / unchecked for error types

Signed-off-by: kim <grufwub@gmail.com>

* add back the used type...

Signed-off-by: kim <grufwub@gmail.com>

* add separate internal getStatus() function for derefThread() that doesn't recurse

Signed-off-by: kim <grufwub@gmail.com>

* improved mention and media attachment error handling

Signed-off-by: kim <grufwub@gmail.com>

* fix log and error format directives

Signed-off-by: kim <grufwub@gmail.com>

* update account deref to match status deref changes

Signed-off-by: kim <grufwub@gmail.com>

* very small code formatting change to make things clearer

Signed-off-by: kim <grufwub@gmail.com>

* add more code comments

Signed-off-by: kim <grufwub@gmail.com>

* improved code commenting

Signed-off-by: kim <grufwub@gmail.com>

* only check for required further derefs if needed

Signed-off-by: kim <grufwub@gmail.com>

* improved cache invalidation

Signed-off-by: kim <grufwub@gmail.com>

* tweak cache restarting to use a (very small) backoff

Signed-off-by: kim <grufwub@gmail.com>

* small readability changes and fixes

Signed-off-by: kim <grufwub@gmail.com>

* fix account sync issues

Signed-off-by: kim <grufwub@gmail.com>

* fix merge conflicts + update account enrichment to accept already-passed accountable

Signed-off-by: kim <grufwub@gmail.com>

* remove secondary function declaration

Signed-off-by: kim <grufwub@gmail.com>

* normalise dereferencer get status / account behaviour, fix remaining tests

Signed-off-by: kim <grufwub@gmail.com>

* fix remaining rebase conflicts, finish commenting code

Signed-off-by: kim <grufwub@gmail.com>

* appease the linter

Signed-off-by: kim <grufwub@gmail.com>

* add source file header

Signed-off-by: kim <grufwub@gmail.com>

* update to use TIMESTAMPTZ column type instead of just TIMESTAMP

Signed-off-by: kim <grufwub@gmail.com>

* don't pass in 'updated_at' to UpdateEmoji()

Signed-off-by: kim <grufwub@gmail.com>

* use new ap.Resolve{Account,Status}able() functions

Signed-off-by: kim <grufwub@gmail.com>

* remove the somewhat confusing rescoping of the same variable names

Signed-off-by: kim <grufwub@gmail.com>

* update migration file name, improved database delete error returns

Signed-off-by: kim <grufwub@gmail.com>

* formatting

Signed-off-by: kim <grufwub@gmail.com>

* improved multi-delete database functions to minimise DB calls

Signed-off-by: kim <grufwub@gmail.com>

* remove unused type

Signed-off-by: kim <grufwub@gmail.com>

* fix delete statements

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-12 11:15:54 +02:00
Natsu Kagami ba5a464ca5
[chore] Prefer JSON errors in API endpoints (#1766)
* Default to JSON over HTML for error handling

* Change the default error display for web endpoints to html
2023-05-12 10:16:41 +02:00
f0x52 265cc32516
use more semantic headers for profile page (#1765) 2023-05-11 20:36:14 +02:00
f0x52 9cc9ffc5a7
[frontend] Profiles with fields & more (#1764)
* redesign status template

* separate index page styling

* redesign profile template

* fix header styling/wrapping

* remove old spoiler js

* fix status cw button wrapping

* fix status info variables

* profile responsiveness, accessibility tweaks

* fix variable use, mobile

* remove duplicate id's

* rss icon, fix indent

* fix toot border-radius

* fix toot spacing

* emojify and html profile fields

* refactor (sensitive) media rendering

* plaintext profile fields

* bundle plyr icon svg

* only pause video when switching photoswipe slides

* yarn upgrade

* profile fields formatting

* replace uglifyify with @browserify updated fork

* fix profile field templating (yet again)

* fix React classes

* testrig: add testing profile field for admin user

* fix sensitive media interactions

* Revert "testrig: add testing profile field for admin user"

This reverts commit 80490c183e6639ce5b57fcfca6772d8f96df8706.

* settings interface wrapping

* fix reported toot styling

* add role to profile sr-only text

* comment fallback rule

* remove currently unused image description lacking indicator
2023-05-11 17:46:32 +02:00
Dominik Süß 6392e00653
feat: initial tracing support (#1623) 2023-05-09 18:19:48 +01:00
tobi 878ed48de3
[bugfix] Don't try to get user when serializing local instance account (#1757) 2023-05-09 16:05:35 +01:00
kim 11e843a273
[bugfix] fix possible domain blockcache nil ptr + add debug String() func (#1755) 2023-05-09 15:18:51 +01:00
kim 8275d70e38
[bugfix] update go-cache version to support multi-keying (#1756)
* update go-cache version to support multi-keying

Signed-off-by: kim <grufwub@gmail.com>

* improved cache invalidation

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-09 16:17:43 +02:00
tobi 65cd1acbdf
[chore] tidy + update StatusToAPIStatus (#1754) 2023-05-09 13:25:48 +02:00
tobi 0e29f1f5bb
[feature] Enable federation in/out of profile PropertyValue fields (#1722)
Co-authored-by: kim <grufwub@gmail.com>
Co-authored-by: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
2023-05-09 11:16:10 +01:00
tobi cbb9e2d3f0
[chore/performance] Make sender multiplier configurable (#1750) 2023-05-08 18:03:38 +01:00
tobi 37b4d9d179
[bugfix] Punycode fixes (#1743)
Co-authored-by: kim <grufwub@gmail.com>
Co-authored-by: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
2023-05-07 18:53:21 +01:00
Daenney b7dd32da42
[bugfix] Return languages in api/v1/instance (#1741)
It turns out that in Masto v2.3.0 the languages key was added to the V1
Instance and that it's effectively mandatory. Though in GtS we don't
really have this concept yet, some apps will explode if the languages
key is missing altogether. So at least return the empty array on V1 too
in the hopes that it makes things work well enough.

For history's sake, you can see the attributes that will get serialised
in
f877aa9d70/app/serializers/rest/v1/instance_serializer.rb (L6-L9).
Because the attribute does not have a conditional defined for it,
there isn't a filter that optionally omits it, or a def languages to
modify the behaviour the attribute is effectively always included and
serialised.

Fixes: #1662
2023-05-06 22:38:19 +02:00
Daenney 6d138588d8
[feature] Implement the preferences client API (#1740)
This adds the preferences endpoint to our Mastodon Client API
implementation. It's a read-only endpoint that returns a number of
user preferences. Applications can query these settings when logging in
a user (for the first time) to configure themselves.
2023-05-06 17:42:58 +02:00
tobi 9b4b4d4eb8
[chore] update readthedocs deps, use conda (#1742)
* [chore] update readthedocs deps, use conda

* work this time thx
2023-05-06 17:33:37 +02:00
tobi 5027d0ced2
[bugfix] Serve correct 'application/jrd+json' content type for webfinger requests (#1738)
* [bugfix] Return `application/jrd+json` from webfinger queries

* update finger req content-type
2023-05-04 12:28:50 +02:00
tobi 4a012acd52
[bugfix] Rework notifs to use min_id for paging up (#1734) 2023-05-04 12:27:24 +02:00
tobi a6ec2a5bc2
[bugfix] Fix invalid og:description on account w/ empty note (#1733) 2023-05-03 16:18:34 +02:00
Daenney c41c1f90a6
[chore] Hide vendor from diffs (#1729)
Linguist already classifies vendor/ as vendored files, meaning they
don't count towards things like a repo language stat, but are still
shows in diffs.

By classifying them as generated instead they're not only excluded from
langauge stats but also hidden in diffs.
2023-05-02 21:11:41 +01:00
kim 3ff1391a9d
[performance] replace domain block cache with an in-memory radix trie (#1714)
* replace domain block cache with an in-memory radix tree

Signed-off-by: kim <grufwub@gmail.com>

* fix domain block cache init

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-05-01 12:36:46 +02:00
dependabot[bot] 66f09a8d93
[chore]: Bump modernc.org/sqlite from 1.22.0 to 1.22.1 (#1726)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.22.0 to 1.22.1.
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.22.0...v1.22.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 11:03:30 +02:00
dependabot[bot] e9de7bec15
[chore]: Bump github.com/go-playground/validator/v10 (#1724)
Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.12.0 to 10.13.0.
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.12.0...v10.13.0)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 11:02:44 +02:00
dependabot[bot] ab7f518f57
[chore]: Bump github.com/KimMachineGun/automemlimit from 0.2.5 to 0.2.6 (#1723)
Bumps [github.com/KimMachineGun/automemlimit](https://github.com/KimMachineGun/automemlimit) from 0.2.5 to 0.2.6.
- [Release notes](https://github.com/KimMachineGun/automemlimit/releases)
- [Commits](https://github.com/KimMachineGun/automemlimit/compare/v0.2.5...v0.2.6)

---
updated-dependencies:
- dependency-name: github.com/KimMachineGun/automemlimit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 11:01:36 +02:00
dependabot[bot] 5904e3b4ee
[chore]: Bump github.com/miekg/dns from 1.1.53 to 1.1.54 (#1727)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.53 to 1.1.54.
- [Release notes](https://github.com/miekg/dns/releases)
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.53...v1.1.54)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-01 11:00:41 +02:00
kim ead286a67b
[bugfix] tweak httpclient error handling again ... (#1721)
* check for tls, x509 errors using string.Contains() since crypto/tls sucks

Signed-off-by: kim <grufwub@gmail.com>

* use 2* maxprocs

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-04-30 10:11:18 +02:00
kim 68b91d2128
[performance] tweak http client error handling (#1718)
* update errors library, check for more TLS type error in http client

Signed-off-by: kim <grufwub@gmail.com>

* bump cache library version to match errors library

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-04-29 18:44:20 +02:00
tobi 8b1e2288d8
[feature] Add GET endpoint for single notification (#1719) 2023-04-29 17:29:51 +01:00
Mal Hancock fdd2487cfb
[bugfix] add From to email header (#1717)
* add From to email header

* update tests
2023-04-29 11:47:14 +02:00
kim 6a29c5ffd4
[performance] improved request batching (removes need for queueing) (#1687)
* revamp http client to not limit requests, instead use sender worker

Signed-off-by: kim <grufwub@gmail.com>

* remove separate sender worker pool, spawn 2*GOMAXPROCS batch senders each time, no need for transport cache sweeping

Signed-off-by: kim <grufwub@gmail.com>

* improve batch senders to keep popping recipients until remote URL found

Signed-off-by: kim <grufwub@gmail.com>

* fix recipient looping issue

Signed-off-by: kim <grufwub@gmail.com>

* fix missing mutex unlock

Signed-off-by: kim <grufwub@gmail.com>

* move request id ctx key to gtscontext, finish filling out more code comments, add basic support for not logging client IP

Signed-off-by: kim <grufwub@gmail.com>

* slight code reformatting

Signed-off-by: kim <grufwub@gmail.com>

* a whitespace

Signed-off-by: kim <grufwub@gmail.com>

* remove unused code

Signed-off-by: kim <grufwub@gmail.com>

* add missing license headers

Signed-off-by: kim <grufwub@gmail.com>

* fix request backoff calculation

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-04-28 17:45:21 +02:00
tobi 6b4f6dc755
[bugfix] Fix remaining mangled URI escaping issues in statuses + accounts (#1712)
* start fiddling with normalize + extract functions

* normalize attachment name (image description)

* NormalizeAccountableSummary

* normalize summary + name
2023-04-26 16:17:22 +01:00
0hlov3 ae9d432f13
[docs] Migrates Chart Location (#1708) 2023-04-24 13:49:44 +02:00
dependabot[bot] 49395f2464
[chore]: Bump modernc.org/sqlite from 1.21.1 to 1.22.0 (#1711)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.21.1 to 1.22.0.
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.21.1...v1.22.0)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-24 13:49:21 +02:00
tobi fd3bf9284d
[bugfix] fix small config typos (#1707) 2023-04-19 14:22:13 +02:00
OniriCorpe f3066a11bf
[chore] Replacing all Pinafore mentions to Semaphore ones (#1689) 2023-04-19 13:50:10 +02:00
dependabot[bot] a3d2774db5
[chore]: Bump codeberg.org/gruf/go-cache/v3 from 3.2.3 to 3.2.5 (#1701)
Bumps codeberg.org/gruf/go-cache/v3 from 3.2.3 to 3.2.5.

---
updated-dependencies:
- dependency-name: codeberg.org/gruf/go-cache/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-19 13:46:42 +02:00
dependabot[bot] c5f61c456b
[chore]: Bump mvdan.cc/xurls/v2 from 2.4.0 to 2.5.0 (#1702)
Bumps [mvdan.cc/xurls/v2](https://github.com/mvdan/xurls) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/mvdan/xurls/releases)
- [Commits](https://github.com/mvdan/xurls/compare/v2.4.0...v2.5.0)

---
updated-dependencies:
- dependency-name: mvdan.cc/xurls/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-19 13:44:20 +02:00
dependabot[bot] ef3004b77f
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.50 to 7.0.52 (#1703)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.50 to 7.0.52.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.50...v7.0.52)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-19 13:43:42 +02:00
Phil Hagelberg 922bd89f17
[docs] Explain that markdown is enabled on the user settings page. (#1699)
* Explain that markdown is enabled on the user settings page.

The current wording seems to imply that the input formatting can be
set on a per-post basis, which no client currently supports. It's not
clear that you have to go to the user settings page to change it.

* Update FAQ; some of the missing features are not missing any more!
2023-04-19 13:42:47 +02:00
Umar Getagazov cb1f935013
[bugfix] Fix the bookmarks list API endpoint returning an empty array (#1700) 2023-04-19 13:42:00 +02:00
tobi 093cf2ab12
[feature] Receive notification when followed account posts (if desired) (#1680)
* start working on notifs for new posts

* tidy up a bit

* update swagger

* carry over show reblogs + notify from follow req

* test notify on status post

* update column slice

* dedupe update logic + add tests

* fix own boosts not being timelined

* avoid type check, passing unnecessary accounts

* remove unnecessary 'inReplyToID' check

* add a couple todo's for future db functions
2023-04-10 20:56:02 +01:00
dependabot[bot] c01d2f9b44
[chore]: Bump golang.org/x/oauth2 from 0.6.0 to 0.7.0 (#1684)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 13:51:03 +02:00
dependabot[bot] 1d8f9c6b16
[chore]: Bump golang.org/x/crypto from 0.7.0 to 0.8.0 (#1685)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 12:35:05 +02:00
dependabot[bot] 014d7ac131
[chore]: Bump github.com/spf13/cobra from 1.6.1 to 1.7.0 (#1686)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.6.1 to 1.7.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.6.1...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 12:14:21 +02:00
dependabot[bot] 158facf011
[chore]: Bump golang.org/x/image from 0.6.0 to 0.7.0 (#1682)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-10 12:12:46 +02:00
tobi f28ed21343
[bugfix] Fix single author threads not appearing in home timeline (#1679) 2023-04-08 12:56:55 +02:00
tobi fb41d2d48f
[bugfix] warn on maxprocs error instead of failing (#1678)
* [bugfix] warn on maxprocs error instead of failing

* info instead of warn
2023-04-08 11:51:24 +02:00
kim e46323c207
[bugfix] visibility caching and hometimeline (#1675)
* fix visibility caching to use correct type key

Signed-off-by: kim <grufwub@gmail.com>

* check for ID check > max possible ID

Signed-off-by: kim <grufwub@gmail.com>

* update home timeline code to include relevant threads to owner (e.g. between mutuals/follows)

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-04-06 17:11:25 +02:00
tobi 3510454768
[bugfix/chore] Refactor timeline code (#1656)
* start poking timelines

* OK yes we're refactoring, but it's nothing like the last time so don't worry

* more fiddling

* update tests, simplify Get

* thanks linter, you're the best, mwah mwah kisses

* do a bit more tidying up

* start buggering about with the prepare function

* fix little oopsie

* start merging lists into 1

* ik heb een heel zwaar leven
nee nee echt waar

* hey it works we did it reddit

* regenerate swagger docs

* tidy up a wee bit

* adjust paging

* fix little error, remove unused functions
2023-04-06 12:43:13 +01:00
tobi c54510bc74
[bugfix] Normalize status content (don't parse status content as IRI) (#1665)
* start fannying about

* finish up Normalize

* tidy up

* pin to tag

* move errors about just a little bit
2023-04-06 12:19:55 +01:00
tobi 4f322f527f
[bugfix] Always serialize orderedItems as array (#1673) 2023-04-06 12:16:53 +01:00
tobi 8d2a76c58c
[bugfix] Add proper constraints on status faves, dedupe (#1674)
* [bugfix] Start working on multiple like issue

* finish up
2023-04-05 20:10:05 +02:00
tobi 36a2131375
[chore] Update templates license headers (#1672) 2023-04-04 11:33:11 +02:00
tobi b847af1dbd
[bugfix] Add idempotency-key to allowed CORS headers (#1670) 2023-04-03 12:01:24 +02:00
dependabot[bot] 9c209fe6e4
[chore]: Bump modernc.org/sqlite from 1.21.0 to 1.21.1 (#1669)
Bumps [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) from 1.21.0 to 1.21.1.
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.21.0...v1.21.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-03 11:19:05 +02:00
dependabot[bot] 839fd56ea4
[chore]: Bump github.com/miekg/dns from 1.1.52 to 1.1.53 (#1668)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.52 to 1.1.53.
- [Release notes](https://github.com/miekg/dns/releases)
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.52...v1.1.53)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-03 11:17:28 +02:00
dependabot[bot] 57dc742c76
[chore]: Bump github.com/KimMachineGun/automemlimit from 0.2.4 to 0.2.5 (#1666)
Bumps [github.com/KimMachineGun/automemlimit](https://github.com/KimMachineGun/automemlimit) from 0.2.4 to 0.2.5.
- [Release notes](https://github.com/KimMachineGun/automemlimit/releases)
- [Commits](https://github.com/KimMachineGun/automemlimit/compare/v0.2.4...v0.2.5)

---
updated-dependencies:
- dependency-name: github.com/KimMachineGun/automemlimit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-03 11:16:17 +02:00
tobi 3f9b2336c0
[bugfix/frontend] Preload css styles (#1638) 2023-04-02 14:03:29 +02:00
tobi 60639a6a0e
[bugfix] Fix multiple "updated_at" columns for media updates (#1660)
* [bugfix] Fix multiple "updated_at" columns for media updates

* silly unrelated race condition
2023-03-31 15:19:50 +02:00
tobi d9bbcc60a6
[bugfix] Fix report serialization errors caused by user delete (#1659)
* [bugfix] Fix report serialization errors caused by user delete

* fix tests
2023-03-31 15:01:29 +02:00
tobi 344c7e5cbd
[bugfix] Fix relationship not updating 'following' on accept follow request (#1658) 2023-03-31 11:16:25 +01:00
Julian-Samuel Gebühr fe4ea964cd
[docs] Add MASH as 3rd party packaging (#1654) 2023-03-31 00:00:06 +02:00
kim a5c920a50b
bump go-store version (includes minio) (#1657)
Signed-off-by: kim <grufwub@gmail.com>
2023-03-30 22:39:55 +01:00
f0x52 0746ef741a
[frontend] Settings navigation design (#1652)
* change header image alignment

(cherry picked from commit df1bb339a5c597a2b668cedb3dafec5a390df120)

* big mess navigation refactor

* bit of cleanup

* minor css tweaks

* fix error rendering code for remote emoji

* refactor navigation structure code

* refactor styling

* fix className

* stash

* restructure navigation generation

* url wildcard formatting

* remove un-implemented User menu entry

* remove commented lines

* clarify permissions check

* invert permissions logic for clarity
2023-03-29 12:18:45 +02:00
tobi 6cf6613540
[bugfix] Remove unique constraint on public_key (#1653) 2023-03-28 22:55:51 +02:00
kim de6e3e5f2a
[performance] refactoring + add fave / follow / request / visibility caching (#1607)
* refactor visibility checking, add caching for visibility

* invalidate visibility cache items on account / status deletes

* fix requester ID passed to visibility cache nil ptr

* de-interface caches, fix home / public timeline caching + visibility

* finish adding code comments for visibility filter

* fix angry goconst linter warnings

* actually finish adding filter visibility code comments for timeline functions

* move home timeline status author check to after visibility

* remove now-unused code

* add more code comments

* add TODO code comment, update printed cache start names

* update printed cache names on stop

* start adding separate follow(request) delete db functions, add specific visibility cache tests

* add relationship type caching

* fix getting local account follows / followed-bys, other small codebase improvements

* simplify invalidation using cache hooks, add more GetAccountBy___() functions

* fix boosting to return 404 if not boostable but no error (to not leak status ID)

* remove dead code

* improved placement of cache invalidation

* update license headers

* add example follow, follow-request config entries

* add example visibility cache configuration to config file

* use specific PutFollowRequest() instead of just Put()

* add tests for all GetAccountBy()

* add GetBlockBy() tests

* update block to check primitive fields

* update and finish adding Get{Account,Block,Follow,FollowRequest}By() tests

* fix copy-pasted code

* update envparsing test

* whitespace

* fix bun struct tag

* add license header to gtscontext

* fix old license header

* improved error creation to not use fmt.Errorf() when not needed

* fix various rebase conflicts, fix account test

* remove commented-out code, fix-up mention caching

* fix mention select bun statement

* ensure mention target account populated, pass in context to customrenderer logging

* remove more uncommented code, fix typeutil test

* add statusfave database model caching

* add status fave cache configuration

* add status fave cache example config

* woops, catch missed error. nice catch linter!

* add back testrig panic on nil db

* update example configuration to match defaults, slight tweak to cache configuration defaults

* update envparsing test with new defaults

* fetch followingget to use the follow target account

* use accounnt.IsLocal() instead of empty domain check

* use constants for the cache visibility type check

* use bun.In() for notification type restriction in db query

* include replies when fetching PublicTimeline() (to account for single-author threads in Visibility{}.StatusPublicTimelineable())

* use bun query building for nested select statements to ensure working with postgres

* update public timeline future status checks to match visibility filter

* same as previous, for home timeline

* update public timeline tests to dynamically check for appropriate statuses

* migrate accounts to allow unique constraint on public_key

* provide minimal account with publicKey

---------

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-28 14:03:14 +01:00
Daenney 7d09863393
[feature] Add list command to admin account (#1648)
* [feature] Add list command to admin account

Relates to: #388

* Print booleans as yes/no too
2023-03-27 16:02:26 +02:00
dependabot[bot] 9e1756ce8b
[chore]: Bump github.com/tdewolff/minify/v2 from 2.12.4 to 2.12.5 (#1649)
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.12.4 to 2.12.5.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.12.4...v2.12.5)

---
updated-dependencies:
- dependency-name: github.com/tdewolff/minify/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 15:59:57 +02:00
tobi 1603a7fd48
[chore] License sloth logo + default avatars under CC by-sa 4.0 (#1651) 2023-03-27 15:36:08 +02:00
kim 883dc5476b
bump go-runners version to fix possible race in Processing{Media,Emoji} (#1646)
Signed-off-by: kim <grufwub@gmail.com>
2023-03-24 23:07:50 +00:00
tobi e8595f0c64
[chore] Refactor account deleting/block logic, tidy up some other processing things (#1599)
* start refactoring account deletion

* update to use state.DB

* further messing about

* some more tidying up

* more tidying, cleaning, nice-making

* further adventures in refactoring and the woes of technical debt

* update fr accept/reject

* poking + prodding

* fix up deleting

* create fave uri

* don't log using requestingAccount.ID because it might be nil

* move getBookmarks function

* use exists query to check for status bookmark

* use deletenotifications func

* fiddle

* delete follow request notif

* split up some db functions

* Fix possible nil pointer panic

* fix more possible nil pointers

* fix license headers

* warn when follow missing (target) account

* return wrapped err when bookmark/fave models can't be retrieved

* simplify self account delete

* warn log likely race condition

* de-sillify status delete loop

* move error check due north

* warn when unfollowSideEffects has no target account

* warn when no boost account is found

* warn + dump follow when no account

* more warnings

* warn on fave account not set

* move for loop inside anonymous function

* fix funky logic

* don't remove mutual account items on block;
do make sure unfollow occurs in both directions!
2023-03-20 18:10:08 +00:00
dependabot[bot] 276d773438
[chore]: Bump github.com/miekg/dns from 1.1.51 to 1.1.52 (#1636)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.51 to 1.1.52.
- [Release notes](https://github.com/miekg/dns/releases)
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.51...v1.1.52)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:36:34 +01:00
dependabot[bot] 78aebf5088
[chore]: Bump github.com/microcosm-cc/bluemonday from 1.0.22 to 1.0.23 (#1635)
Bumps [github.com/microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday) from 1.0.22 to 1.0.23.
- [Release notes](https://github.com/microcosm-cc/bluemonday/releases)
- [Commits](https://github.com/microcosm-cc/bluemonday/compare/v1.0.22...v1.0.23)

---
updated-dependencies:
- dependency-name: github.com/microcosm-cc/bluemonday
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:07:14 +01:00
dependabot[bot] ac74256295
[chore]: Bump go.uber.org/automaxprocs from 1.5.1 to 1.5.2 (#1633)
Bumps [go.uber.org/automaxprocs](https://github.com/uber-go/automaxprocs) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/uber-go/automaxprocs/releases)
- [Changelog](https://github.com/uber-go/automaxprocs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/automaxprocs/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: go.uber.org/automaxprocs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:06:53 +01:00
dependabot[bot] 4096e7076a
[chore]: Bump github.com/go-playground/validator/v10 (#1637)
Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.11.2 to 10.12.0.
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.11.2...v10.12.0)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:05:46 +01:00
tobi 66bedc4747
[bugfix] Use account ID host as accDomain if 2nd webfinger lookup fails (#1630) 2023-03-19 15:45:13 +00:00
tobi 7db81cde44
[feature] Email notifications for new / closed moderation reports (#1628)
* start fiddling about with email sending to allow multiple recipients

* do some fiddling

* notifs working

* notify on closed report

* finishing up

* envparsing

* use strings.ContainsAny
2023-03-19 13:11:46 +01:00
Daenney 9c55c07be9
[docs] Update docs on how to login (#1626)
This adds a section to the docs instructing how to ensure apps will be
able to successfully login to an instance when host- and account-domain
differ.

Resolves #1609
2023-03-16 11:43:19 +01:00
tobi 196cd88b1c
[feature] Allow admins to send test emails (#1620)
* [feature] Allow admins to send test emails

* implement unwrap on new error type

* add + use gtserror types

* GoToSocial Email Test -> GoToSocial Test Email

* add + use getInstance db call

* removed unused "unknown" error type
2023-03-14 16:11:04 +00:00
tobi d5529d6c9f
[chore] fix + update swagger docs (#1622) 2023-03-14 10:56:34 +01:00
dependabot[bot] 19e058466d
[chore]: Bump github.com/ulule/limiter/v3 from 3.11.0 to 3.11.1 (#1616)
Bumps [github.com/ulule/limiter/v3](https://github.com/ulule/limiter) from 3.11.0 to 3.11.1.
- [Release notes](https://github.com/ulule/limiter/releases)
- [Commits](https://github.com/ulule/limiter/compare/v3.11.0...v3.11.1)

---
updated-dependencies:
- dependency-name: github.com/ulule/limiter/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:59:49 +01:00
dependabot[bot] e448260e86
[chore]: Bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#1618)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:56:14 +01:00
dependabot[bot] 86dafa6871
[chore]: Bump github.com/abema/go-mp4 from 0.10.0 to 0.10.1 (#1617)
Bumps [github.com/abema/go-mp4](https://github.com/abema/go-mp4) from 0.10.0 to 0.10.1.
- [Release notes](https://github.com/abema/go-mp4/releases)
- [Commits](https://github.com/abema/go-mp4/compare/v0.10.0...v0.10.1)

---
updated-dependencies:
- dependency-name: github.com/abema/go-mp4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:52:57 +01:00
dependabot[bot] 34f453878b
[chore]: Bump golang.org/x/image from 0.5.0 to 0.6.0 (#1615)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:51:50 +01:00
dependabot[bot] 0a864623f3
[chore]: Bump codeberg.org/gruf/go-kv from 1.6.0 to 1.6.1 (#1619)
Bumps codeberg.org/gruf/go-kv from 1.6.0 to 1.6.1.

---
updated-dependencies:
- dependency-name: codeberg.org/gruf/go-kv
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 07:52:13 +00:00
f0x52 6e10175229
update license headers (#1612) 2023-03-12 17:49:06 +00:00
Daenney 5e2bf0bdca
[chore] Improve copyright header handling (#1608)
* [chore] Remove years from all license headers

Years or year ranges aren't required in license headers. Many projects
have removed them in recent years and it avoids a bit of yearly toil.

In many cases our copyright claim was also a bit dodgy since we added
the 2021-2023 header to files created after 2021 but you can't claim
copyright into the past that way.

* [chore] Add license header check

This ensures a license header is always added to any new file. This
avoids maintainers/reviewers needing to remember to check for and ask
for it in case a contribution doesn't include it.

* [chore] Add missing license headers

* [chore] Further updates to license header

* Use the more common // indentend comment format
* Remove the hack we had for the linter now that we use the // format
* Add SPDX license identifier
2023-03-12 16:00:57 +01:00
tobi a772d4d98e
[chore] Fix opengraph properties (#1611) 2023-03-12 14:14:33 +01:00
darrinsmart e323a930bf
[feature] Support multiple subscriptions on single websocket connection (#1489)
- Allow Oauth authentication on websocket endpoint
- Make streamType query parameter optional
- Read websocket commands from client and update subscriptions
2023-03-11 11:10:58 +01:00
f0x52 cb2f84e551
[frontend/fix] Mobile css tweaks (#1605)
* mobile css tweaks

* bulk process list mobile css
2023-03-11 10:49:44 +01:00
Daenney a312238e79
[feature] Provide .well-known/host-meta endpoint (#1604)
* [feature] Provide .well-known/host-meta endpoint

This adds the host-meta endpoint as Mastodon clients use this to
discover the API domain to use when the host and account domains aren't
the same.

* Address review comments
2023-03-09 17:55:45 +00:00
Daenney 9ba35c65eb
[bug] Handle 410 on webfinger properly (#1601)
When we receive an HTTP 410 on webfinger it means the resource we asked
for (the account) is gone, but the endpoint itself responded. In such
cases we want to treat the request as successful from a cache (renewal)
point of view, while still returning an error from Finger.

Follow-up for #1588
2023-03-09 10:17:11 +00:00
kim d0dee8d0b6
[chore] improved enrichAccount() logging (#1602)
* slight refactor and improved logging on failed webfinger in enrichAccount()

* use correct log format directive

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-03-08 17:19:49 +00:00
Daenney e397272fe8
[feature] Discover webfinger through host-meta (#1588)
* [feature] Discover webfinger through host-meta

This implements a fallback for discovering the webfinger endpoint in
case the /.well-known/webfinger endpoint wasn't properly redirected.
Some instances do this because the recommendation used to be to use
host-meta for the webfinger redirect in the before times.

Closes #1558.

* [bug] Ensure we only ever update cache on success

* [chore] Move finger tests to their own place

This adds a test suite for transport and moves the finger cache tests
into there instead of abusing the search test suite.

* [chore] cleanup the test a bit more

We don't really need a separate function for the oddly located webfinger
response as we check the full URL string anyway

* Address review comments

* [chore] update config example

* [chore] access DB only through state in controller
2023-03-08 12:57:41 +00:00
tobi b344c2c8f4
[chore] Update uptrace/bun and modernc/sqlite dependencies (#1598)
* [chore] Update bun from 1.1.10 -> 1.1.12

* [chore] bump modernc/sqlite 1.20.4 -> 1.21.0
2023-03-06 11:00:53 +01:00
kim d8d5818b47
[bugfix] internal server error on search not found (#1590)
* add error value wrapping, include status code / not found flags from transport errors, update error usages

Signed-off-by: kim <grufwub@gmail.com>

* add code commenting for gtserror functions

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-03-06 10:38:43 +01:00
zowhoey f518f649f8
[feature] Add support for profile fields (#1483)
* Add go-playground/form pkg

* [feature] Add support for profile fields

* Add field attributes test

* Validate profile fields form

* Add profile field validation tests

* Add Field Attributes definition to swagger

---------

Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com>
2023-03-06 10:30:19 +01:00
dependabot[bot] 24f6a447f3
[chore]: Bump github.com/jackc/pgx/v4 from 4.17.2 to 4.18.1 (#1595)
Bumps [github.com/jackc/pgx/v4](https://github.com/jackc/pgx) from 4.17.2 to 4.18.1.
- [Release notes](https://github.com/jackc/pgx/releases)
- [Changelog](https://github.com/jackc/pgx/blob/v4.18.1/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v4.17.2...v4.18.1)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 10:12:45 +01:00
dependabot[bot] 9f36507c45
[chore]: Bump golang.org/x/oauth2 from 0.5.0 to 0.6.0 (#1597)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 08:26:44 +00:00
dependabot[bot] b004b4dae9
[chore]: Bump golang.org/x/crypto from 0.6.0 to 0.7.0 (#1593)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 08:16:14 +00:00
dependabot[bot] 06524ac259
[chore]: Bump golang.org/x/text from 0.7.0 to 0.8.0 (#1594)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 08:09:17 +00:00
Daenney 65aeeb4442
[chore] Print human readable config (#1589)
This changes the config action to print the config in a more human
readable format, indented by 4 spaces and with newlines.

Thanks to this, we can now reasonably construct some JSON in the
envparsing shell script, without needing utilities like jd. It does
assume cat is available in order to not change the shebang to bash.

With the expected JSON now being one key per line it should make it much
easier for multiple PRs that change something around config not to
collide in merge conflicts.
2023-03-04 20:56:50 +00:00
Daenney d2f6de0185
[feature] Allow loading TLS certs from disk (#1586)
Currently, GtS only supports using the built-in LE client directly for
TLS. However, admins may still want to use GtS directly (so without a
reverse proxy) but with certificates provided through some other
mechanism. They may have some centralised way of provisioning these
things themselves, or simply prefer to use LE but with a different
challenge like DNS-01 which is not supported by autocert.

This adds support for loading a public/private keypair from disk instead
of using LE and reconfigures the server to use a TLS listener if we
succeed in doing so.

Additionally, being able to load TLS keypair from disk opens up the path
to using a custom CA for testing purposes avoinding the need for a
constellation of containers and something like Pebble or Step CA to
provide LE APIs.
2023-03-04 17:24:02 +00:00
kim ef074752d0
use updateattachment when updating to ensure cache is invalidated (#1587)
Signed-off-by: kim <grufwub@gmail.com>
2023-03-04 14:53:21 +00:00
kim a8e6bdfa33
[performance] cache media attachments (#1525)
* replace concurrency worker pools with base models in State.Workers, update code and tests accordingly

* add media attachment caching, slightly tweak default cache config

* further tweak default cache config values

* replace other media attachment db calls to go through cache

* update envparsing test

* fix delete media attachment sql

* fix media sql query

* invalidate cached media entries during status create / update

* fix envparsing test

* fix typo in panic log message...

* add 'updated_at' column during UpdateAttachment

* remove unused func

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-03-03 23:02:23 +00:00
tobi 5be59f4a25
[bugfix] Federate status delete using just the URI (#1584) 2023-03-03 19:56:34 +00:00
tobi 88eefd0aeb
[bugfix] Clamp admin report limit <1 to 100 (#1583)
* [bugfix] Clamp report limit <1 to 100

* add + update tests
2023-03-03 14:01:11 +01:00
tobi 29f8c51ab8
[bugfix] Fix unpinning statuses not working (#1582)
And also fix unpinning/pinning potentially leaking the ID of followers-only statuses through returning 422 instead of 404.

Also tests!
2023-03-03 13:35:49 +01:00
kim fe6c8b8152
[bugfix] on deref new account, check db again for account on ErrAlreadyExists (#1581)
Signed-off-by: kim <grufwub@gmail.com>
2023-03-03 09:34:34 +01:00
tobi bfccf4e450
[bugfix] add ON CONFLICT statements to status updates (#1580) 2023-03-02 16:58:23 +01:00
Vyr Cossont e6cde25466
[feature] Advertise rich text formats, support content_type field (#1370)
* Advertise rich text formats, support content_type field

* Update JSON in instance patch tests

* Replace format with content_type everywhere

* update migration to work with both pg and sqlite

* regenerate swagger docs

* update instance serialization + tests

* fix up

* learn to code tobi please, i'm begging you

---------

Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-03-02 12:06:40 +01:00
kim baf933cb9f
[chore] move client/federator workerpools to Workers{} (#1575)
* replace concurrency worker pools with base models in State.Workers, update code and tests accordingly

* improve code comment

* change back testrig default log level

* un-comment-out TestAnnounceTwice() and fix

---------

Signed-off-by: kim <grufwub@gmail.com>
Reviewed-by: tobi
2023-03-01 18:26:53 +00:00
tobi 24cec4e7aa
[feature] Federate pinned posts (aka featuredCollection) in and out (#1560)
* start fiddling

* the ol' fiddle + update

* start working on fetching statuses

* poopy doopy doo where r u uwu

* further adventures in featuring statuses

* finishing up

* fmt

* simply status unpin loop

* move empty featured check back to caller function

* remove unnecessary log.WithContext calls

* remove unnecessary IsIRI() checks

* add explanatory comment about status URIs

* change log level to error

* better test names
2023-03-01 17:52:44 +00:00
kim 87c5c42972
[chore/performance] simplify storage driver to use storage.Storage directly (#1576)
* simply use storage.Storage, removing wrapping KVStore as we don't need KV store locking functionality

Signed-off-by: kim <grufwub@gmail.com>

* fix missing unwrapped function

Signed-off-by: kim <grufwub@gmail.com>

* add code comment

Signed-off-by: kim <grufwub@gmail.com>

* linter, please take my offering in peace

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-03-01 10:44:54 +01:00
Daenney e4c5f9adfd
[chore] Improve unsupported_grant_type error (#1572)
This attempts to provide a slightly more comprehensive error message for
the end user when an incorrect grant type is used. This is not something
the user can typically resolve but should hopefully be informative for
the (client) developer.
2023-02-28 11:38:34 +01:00
tobi d550f0ecbe
[chore] Bump oauth2/v4 -> v4.6.6.6-SSB (#1571) 2023-02-27 16:16:58 +01:00
tobi 4bb3f59324
[chore] bump go, build, and lint version (#1570) 2023-02-27 13:10:54 +01:00
dependabot[bot] 8696a8cdf0
[chore]: Bump github.com/miekg/dns from 1.1.50 to 1.1.51 (#1566)
Bumps [github.com/miekg/dns](https://github.com/miekg/dns) from 1.1.50 to 1.1.51.
- [Release notes](https://github.com/miekg/dns/releases)
- [Changelog](https://github.com/miekg/dns/blob/master/Makefile.release)
- [Commits](https://github.com/miekg/dns/compare/v1.1.50...v1.1.51)

---
updated-dependencies:
- dependency-name: github.com/miekg/dns
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 10:51:12 +01:00
Daenney 6c2bd141f7
[chore] Better diff for envparsing test (#1562)
This checks if jd is availalbe and if so uses that to create the diff
instead. jd can tell you at which (nested) key the values are differing
which makes for more human friendly output.
2023-02-27 10:23:17 +01:00
dependabot[bot] 5a45b6ec6a
[chore]: Bump golang.org/x/oauth2 from 0.4.0 to 0.5.0 (#1564)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 10:22:37 +01:00
dependabot[bot] 752c38b0d5
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.48 to 7.0.49 (#1567)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.48 to 7.0.49.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.48...v7.0.49)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-27 10:21:58 +01:00
Daenney e1b704e06e
[chore] Use latest containers when building (#1554)
This updates the Dockerfile to use the latest image versions for all the
containers that are used when building the final GTS container.
2023-02-26 18:26:24 +01:00
Daenney 55300cbd73
[chore] Inform user on how to get testrig (#1557)
This adds a dummy testrig subcommand when we're not building with DEBUG
set. Now any invocation of gotosocial testrig, plain or with any kind of
subcommands or arguments will result in that error message getting
returned.
2023-02-25 22:26:48 +00:00
Daenney 83be140f0b
[chore] Update vscode launch configuration (#1556)
In order to get testrig we have to build with the debugenv tag and run
with the DEBUG environment variable. Since this is a Debug build this
also updates the launch configuration name to reflect that.

We do not build with `-ldflags="-s -w"` since that strips debug info.

This makes it possible to launch GtS from VS Code in debug mode, set
breakpoints in the editor etc.
2023-02-25 17:15:30 +00:00
Daenney 9cfb69f75d
[feature] Make OIDC admin groups configurable (#1555)
This removes the current default of checking for membership of the admin
or admins group and makes it required to explicitly configure which
groups should grant admin access, if any.

Relying on the implicit default of admin or admins is potentially
dangerous as that group may contain a different subset of people that we
may wish to grant admin access to GtS. This is probably not an issue for
a single-person instance, but for a community instance different admin
groups may exist in an OIDC provider for different applications.

I'm explicitly opting for not defaulting the value of oidc-admin-groups
to admin,admins because I think it's better for those things to be
explicitly configured.
2023-02-25 16:37:39 +00:00
tobi c27b4d7ed0
[feature] Client API endpoints + v. basic web view for pinned posts (#1547)
* implement status pin client api + web handler

* make test names + comments more descriptive

* don't use separate table for status pins

* remove unused add + remove checking

* tidy up + add some more tests
2023-02-25 12:16:30 +00:00
Daenney ecdc8379fa
[chore] Update gin to v1.9.0 (#1553) 2023-02-25 12:12:40 +00:00
tobi 689a10fe17
[bugfix] Fix deleted status causing issues when getting bookmark (#1551)
* [bugfix] Delete bookmark when status deleted

* [chore] Give bookmark processing func some love

* fix paging + embetter tests
2023-02-23 22:11:10 +00:00
Daenney 074f352709
[chore] improve opengraph descripiton tag (#1550)
This changes parseDescription to properly encode things to be safe for
usage without removing things like backslashes that may be relevant.

* text.SanitizePlaintext already calls html.UnescapeString so we don't
  have to do that
* Replace \n with space early
* Remove duplicate white-space by splitting on fields and joining
* HTML-escape the string we have
* For extra certainty, encode the backslash as &bsol;

Fixes #1549
2023-02-22 21:36:18 +00:00
tobi b6fbdc66c1
[chore] Deinterface processor and subprocessors (#1501)
* [chore] Deinterface processor and subprocessors

* expose subprocessors via function calls

* missing license header
2023-02-22 16:05:26 +01:00
tobi adb596600b
[bugfix] Remove initial storage cleanup (#1545) 2023-02-21 10:49:57 +01:00
f0x52 fa70ad757f
[docs] Add site_url for absolute 404 page assets (#1544) 2023-02-21 09:01:10 +01:00
Daenney 40eea3b409
[feature] Use Material theme for docs (#1535)
* [feature] Use Material theme for docs

This changes the theme to use Material with the slate (dark) theme and
the accent colour set to orange. It also replaces the swagger plugin
with one that works correctly with the Material theming.

* Add theme by @f0x52

Co-authored-by: f0x52 <f0x@cthu.lu>

* Enable social cards

The dependencies for cairosvg and pillow can be satisfied on RTD, so
this adds them to our requirements.txt and enables the social plugin.
This generates opengraph and twitter card tags as well as fancy preview
images in GTS colour style for platforms that show that as part of link
previews.

* Update Conda environment.yml

* update theme for swagger, basic light theme option

* dark mode mobile header bg color

---------

Co-authored-by: f0x52 <f0x@cthu.lu>
2023-02-20 23:09:17 +01:00
tobi 87b30a4f91
[docs] correct swagger docs (#1543) 2023-02-20 17:06:36 +01:00
tobi e8a04b7ce1
[bugfix] Fix account roles (#1542)
* Change account role from string to object

* Update tests

* small fixes + swagger docs

---------

Co-authored-by: zowhoey <11893985+zowhoey@users.noreply.github.com>
2023-02-20 17:00:44 +01:00
f0x52 b6143c9ab8
[feature] About page (#1495)
* about page basics

* more info, styling

* update emoji sizing on about page contact card
2023-02-20 16:29:29 +01:00
dependabot[bot] e824e14705
[chore]: Bump golang.org/x/crypto from 0.5.0 to 0.6.0 (#1541)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-20 16:28:09 +01:00
Sam Lade f559d46261
[bugfix] Fix failure to look up remote profiles with duplicate emojis in some cases (#1534)
* Tidy up emoji parsing on profile submission

Don't bother reparsing for emoji unless one of the fields that can have
emoji in it has changed.
Deduplicate emoji between the display name and profile note - I'm not
sure whether this was hurting anything, but better safe.

* Deduplicate emoji when parsing remote accounts

Some servers - Misskey at least - don't deduplicate emoji, so it's
possible to get an account which has the same emoji used in both the
display name and note and therefore includes that emoji twice in its
metadata. When we start trying to put those into our database, we run
into a uniqueness constraint and fall over.

This change just deduplicates at the point of construction of an
account.
2023-02-20 16:27:41 +01:00
kim 2af33d3fb5
Update README.md (#1533) 2023-02-19 16:10:40 +00:00
Daenney 70398891b8
[chore] Move request validation earlier in client (#1531)
This moves checking if the request is valid as early as possible in the
chain. This should ensure that for an invalid request we never bother
acquiring the wait queue and taking up a spot in it.
2023-02-19 11:01:15 +00:00
kim 51c156cca1
pull in latest go-kv, go-cache (#1530)
Signed-off-by: kim <grufwub@gmail.com>
2023-02-19 10:36:38 +01:00
tobi a0068e8915
[bugfix] In Postgres, drop shortcodedomain constraint before creating new emoji table (#1528) 2023-02-18 17:54:51 +01:00
kim a684fc4628
[chore] transport improvements (#1524)
* improve error readability, mark "bad hosts" as fastFail

Signed-off-by: kim <grufwub@gmail.com>

* pull in latest go-byteutil version with byteutil.Reader{}

Signed-off-by: kim <grufwub@gmail.com>

* use rewindable body reader for post requests

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-18 17:02:19 +01:00
dependabot[bot] 3649b231c4
[chore]: Bump golang.org/x/net from 0.5.0 to 0.7.0 (#1523)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.5.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.5.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
2023-02-18 16:52:33 +01:00
mushus fe66a2aed2
[bugfix] Keep png transparency (#1522)
* keep png transparency

* rewrite to switch case
2023-02-18 16:52:15 +01:00
f0x52 59b2e10787
[bugfix] fix oob token route, update templates+css for oob and errors (#1519) 2023-02-18 16:47:42 +01:00
kim 83d8a44020
[chore] update gruf's libs on readme (#1520)
also groups them into a single block to improve readability
2023-02-18 16:45:43 +01:00
dependabot[bot] a822198ebf
[chore]: Bump golang.org/x/image from 0.4.0 to 0.5.0 (#1516)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-18 14:02:49 +00:00
Daenney b4d18887d3
[chore] Update more log calls to include context (#1517)
In #1476 we updated log.WithFields() but we forgot about
log.WithField(). Also updates a few explicit log.Entry{} creations.
2023-02-17 19:05:43 +00:00
Daenney d39280ec33
[bug] Pass context in logging middleware (#1514)
This updates the middleware log.WithField calls that create new loggers
to include the context the first time around. Without it the requestID
does not get logged.

Fixup from #1476
2023-02-17 12:37:57 +01:00
Daenney 1ca5c62e25
[bug] maxprocs set logger to nil (#1512)
We want to set the Logger to nil, but that means we still need to wrap
it in `maxprocs.Logger()`.
2023-02-17 12:31:34 +01:00
Daenney 68e6d08c76
[feature] Add a request ID and include it in logs (#1476)
This adds a lightweight form of tracing to GTS. Each incoming request is
assigned a Request ID which we then pass on and log in all our log
lines. Any function that gets called downstream from an HTTP handler
should now emit a requestID=value pair whenever it logs something.

Co-authored-by: kim <grufwub@gmail.com>
2023-02-17 12:02:29 +01:00
tobi b5993095fa
[bugfix] Set 'discoverable' properly on API accounts (#1511) 2023-02-16 13:20:23 +00:00
tobi 6ee0dc8c7d
[bugfix] Set cache-control max-age dynamically for s3 (#1510)
* [bugfix] set cache-control max-age dynamically for s3

* woops

* double whoops

* time until, thank you linter, bless you, you're the best, no matter what kim says

* aa
2023-02-16 13:18:53 +00:00
Sam Lade 40b584c219
Fix 410 Gone race on account deletes (#1507) 2023-02-15 19:41:16 +00:00
f0x52 b8e1ab312d
use woff(2) fonts for Noto Sans (#1509) 2023-02-15 20:10:18 +01:00
Daenney 4cba90c0f6
[chore] Split the bug template in two (#1500)
Have a separate template for:
* Frontend, with labels bug and frontend and requiring the browser field
* Regular/backend, for other bugs with only the bug label and removal of
  the browser field
2023-02-15 14:37:08 +01:00
wioxjk 674646b79e
[docs] Update config.yaml (#1499)
Made it more clear how GTS accesses S3 buckets
2023-02-15 13:26:18 +01:00
Minecraftchest1 f3eb28a0f5
[docs] Suggest confirming host option in config (#1502)
Having the `Host` config option not match the domain that GTS is exposed on can cause a 400 bad request error on signin.
2023-02-15 13:04:48 +01:00
Daenney fd62847c83
[docs] Fix nginx fileserver caching example (#1506)
* [bug] Fix nginx fileserver caching example

This updates the example to ensure the nginx proxies the request on to
GTS if the file is not found on disk. This can happen due to media
pruning.

* [chore] Set cache-control in nginx to private

This makes the header match with the backend. For things from the
fileserver it may not be appropriate for anything other than a private
cache (i.e the client) to cache things.
2023-02-15 11:44:30 +01:00
f0x52 700ed7769f
[chore] Webkit frontend fixes (#1492)
* fix webkit profile preview layout

* general page layout
2023-02-14 11:58:57 +01:00
tobi 6c6f042290
[bugfix] Return empty result rather than 500 error when searching for blocked domains (#1498)
* [bugfix] Return empty result when searching for blocked domains

* add tests
2023-02-14 11:55:02 +01:00
tobi 561ad71e58
[bugfix] Fix up error getting account avatar/header errors, other small fixes (#1496)
* start fiddling with media + account queries a little

* initialize state when pruning

* allow for unsetting remote media
make sure to wait til media loaded
fix silly tiny bug

* move comment a bit for readability

* slight reformat of fetchRemoteAccount{Avatar,Header}

* fix issue after rebase

* slightly neaten up logic of avatar/header media handling

* remove log prefix (callername log field handles this)

---------

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: kim <grufwub@gmail.com>
2023-02-13 20:19:51 +00:00
kim acc95923da
[performance] processing media and scheduled jobs improvements (#1482)
* replace media workers with just runners.WorkerPool, move to state structure, use go-sched for global task scheduling

* improved code comment

* fix worker tryUntil function, update go-runners/go-sched

* make preprocess functions package public, use these where possible to stop doubled up processing

* remove separate emoji worker pool

* limit calls to time.Now() during media preprocessing

* use Processor{} to manage singular runtime of processing media

* ensure workers get started when media manager is used

* improved error setting in processing media, fix media test

* port changes from processingmedia to processing emoji

* finish code commenting

* finish code commenting and comment-out client API + federator worker pools until concurrency worker pools replaced

* linterrrrrrrrrrrrrrrr

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-13 18:40:48 +00:00
f0x52 76d1b484d0
[docs] move federating with gotosocial documentation into single file (#1494) 2023-02-13 18:34:44 +01:00
tobi 041c8e695e
[chore] Do cache-control in a less silly way to avoid writing header twice (#1481)
* do cache-control in a less silly way to avoid writing header twice

* add comment back in
2023-02-13 12:58:22 +01:00
f0x52 eeca1988ce
[docs] Update user/admin settings docs (#1491)
* update user/admin settings docs

* trigger read-the-docs pr hook

* update menu links

* update images
2023-02-13 12:40:24 +01:00
dependabot[bot] efbc5dab6a
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.47 to 7.0.48 (#1486)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.47 to 7.0.48.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.47...v7.0.48)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 07:46:15 +00:00
dependabot[bot] 33b77b3c1a
[chore]: Bump golang.org/x/image from 0.3.0 to 0.4.0 (#1485)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 07:44:04 +00:00
dependabot[bot] 723175219b
[chore]: Bump modernc.org/sqlite from 1.20.3 to 1.20.4 (#1484)
---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 07:43:16 +00:00
tobi c223c7598d
[bugfix] Set appropriate cache-control when using presigned s3 links (#1480) 2023-02-12 14:42:28 +01:00
tobi 40bc03e717
[chore/performance] Update media prune logic, add extra CLI command (#1474)
* start updating media prune stuff a wee bit

* continue prune / uncache work

* more tidying + consistency stuff

* add prune CLI command

* docs

* arg
2023-02-11 12:48:38 +01:00
kim 70739d32cc
[performance] remove throttling timers (#1466)
* remove throttling timers, support setting retry-after, use retry-after in transport

* remove unused variables

* add throttling-retry-after to cmd flags

* update envparsing to include new throttling-retry-after

* update example config to include retry-after documentation

* also support retry-after formatted as date-time, ensure max backoff time

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-10 20:16:01 +00:00
kim 6ac1dda96f
[chore] small changes missed in previous dereferencer.GetAccount() PRs (#1467)
* small formatting changes, rewrite fetchRemoteMedia to use separate funcs + use mutex lock correctly

* move url parsing before acquiring mutex locks

* use wrapped mutexes to allow safe unlocking. (previously i did a fucky and passed mutex by value...)

* remove unused code

* use consistent map keying for dereferencing headers/avatars

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-10 20:15:23 +00:00
tobi e5e257c259
[bugfix] Fix error on searching for account w/accountDomain by host (#1465) 2023-02-09 10:34:44 +01:00
tobi 95715f9251
[performance] Don't fetch avatar + header if uri hasn't changed (#1463) 2023-02-09 09:27:07 +01:00
f0x52 65b19411a4
[chore] Fix report username wrapping (#1464)
* fix report username wrapping

* move report status to separate line on portrait orientation
2023-02-09 09:26:35 +01:00
tobi 27e95fd123
[chore/bugfix] Serve + throttle publickey separately from rest of ActivityPub API (#1461)
* serve publickey separately from AP, don't throttle it

* update nginx cache documentation, cache main-key too

* throttle public key, but separately from other endpoints
2023-02-08 15:10:56 +01:00
f0x52 52fbb3e584
[bugfix] fix 'steal this look' form, uncheck entries after processing (#1454) 2023-02-07 18:34:54 +01:00
tobi 4e4da19720
[bugfix] Use SignatureCheck middleware for web profile endpoints too (#1451) 2023-02-07 14:57:09 +01:00
f0x52 0ed50c172e
[chore/frogend] domain blocklist layout on smaller screens (#1436) 2023-02-07 10:00:13 +01:00
Daniele Sluijters b63b1b6f55
[chore] Update bug report template (#1437)
This adds a line to the bug report template to indicate that
compatibility issues with closed source clients should be reported to
developers of that client instead.
2023-02-07 09:59:44 +01:00
Sam Lade ad6ab037e4
[bugfix] don't trash emoji in profile fields on edit (#1440) 2023-02-07 09:58:36 +01:00
kim ac2bdbbc62
[bugfix] fix file range length calculation being off by 1 (#1448)
* small formatting change

* fix range handling new length calculation

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-07 08:51:15 +00:00
Sam Lade 6a6647d68b
Ignore missing files when cleaning up media (#1435) 2023-02-06 14:58:54 +00:00
kim 02767bfc7d
[performance] remove local copying of file for satisfying range headers (#1421)
* remove local copying of file for satisfying range headers

Signed-off-by: kim <grufwub@gmail.com>

* remove unused import

Signed-off-by: kim <grufwub@gmail.com>

* fix range header reader limit calculation

Signed-off-by: kim <grufwub@gmail.com>

---------

Signed-off-by: kim <grufwub@gmail.com>
2023-02-06 09:50:16 +01:00
tobi 75e1b9c896
[bugfix] fix old password hash staying in cache (#1432) 2023-02-06 09:44:13 +01:00
f0x52 83b522a1b6
[feature/Frogend] basic report admin interface (#1424)
* basic listing of reports

* report detail overview, resolving

* report detail styling tweaks

* linter fixes
2023-02-06 09:33:47 +01:00
f0x52 47daddc10c
[chore/frogend] Restructure form data default values / update from Query data (#1422)
* eslint: set console use to error to catch debug littering in CI

* remove debug logging

* some form field restructuring, fixes submitted updates not being reflected

* more form field restructuring

* remove debug logger

* simplify field updates

* fix react state set during render when submitting import file

* className instead of class

* show Select hints again
2023-02-06 09:19:56 +01:00
dependabot[bot] 0a9874329d
[chore]: Bump codeberg.org/gruf/go-runners from 1.4.0 to 1.5.1 (#1428)
Bumps codeberg.org/gruf/go-runners from 1.4.0 to 1.5.1.

---
updated-dependencies:
- dependency-name: codeberg.org/gruf/go-runners
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 08:08:22 +00:00
dependabot[bot] 1df25a3592
[chore]: Bump github.com/yuin/goldmark from 1.5.3 to 1.5.4 (#1427)
Bumps [github.com/yuin/goldmark](https://github.com/yuin/goldmark) from 1.5.3 to 1.5.4.
- [Release notes](https://github.com/yuin/goldmark/releases)
- [Commits](https://github.com/yuin/goldmark/compare/v1.5.3...v1.5.4)

---
updated-dependencies:
- dependency-name: github.com/yuin/goldmark
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 09:06:57 +01:00
dependabot[bot] dae14cc0eb
[chore]: Bump github.com/ulule/limiter/v3 from 3.10.0 to 3.11.0 (#1429)
Bumps [github.com/ulule/limiter/v3](https://github.com/ulule/limiter) from 3.10.0 to 3.11.0.
- [Release notes](https://github.com/ulule/limiter/releases)
- [Commits](https://github.com/ulule/limiter/compare/v3.10.0...v3.11.0)

---
updated-dependencies:
- dependency-name: github.com/ulule/limiter/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 09:06:04 +01:00
tobi 7f3245738d
[chore] stub /api/v1/featured_tags endpoint (#1420) 2023-02-05 10:50:09 +01:00
tobi 80c26d61f7
[bugfix] Allow instance thumbnail description to be set separately from image (#1417) 2023-02-04 15:53:11 +01:00
tobi 04ac3f8acf
[bugfix] Fix password change keys (#1416) 2023-02-04 12:40:35 +01:00
kim abe9447d28
fix cache startup (#1414)
Signed-off-by: kim <grufwub@gmail.com>
2023-02-03 20:16:11 +00:00
kim 33aee1b1e9
[chore] reformat GetAccount() functionality, support updating accounts based on last_fetch (#1411)
* reformat GetAccount() functionality, and add UpdateAccount() function.

* use fetched_at instead of last_webfingered_at

* catch local "not found" errors. small formatting / error string changes

* remove now unused error type

* return nil when wrapping nil error

* update expected error messages

* return correct url for foss satan webfinger

* add AP model for Some_User

* normalize local domain

* return notretrievable where appropriate

* expose NewErrNotRetrievable

* ensure webfinger for new accounts searched by uri

* update local account short circuit

* allow enrich to fail for already-known accounts

* remove unused LastWebfingeredAt

* expose test maps on mock http client

* update Update test

* reformat GetAccount() functionality, and add UpdateAccount() function.

* use fetched_at instead of last_webfingered_at

* catch local "not found" errors. small formatting / error string changes

* remove nil error checks (we shouldn't be passing nil errors to newError() initializers)

* remove mutex unlock on transport init fail (it hasn't yet been locked!)

* woops add back the error wrapping to use ErrNotRetrievable

* caches were never being started... 🙈

---------

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2023-02-03 20:03:05 +00:00
f0x52 a59dc855d9
[feature/frogend] (Mastodon) domain block CSV import (#1390)
* checkbox-list styling with taller <p> element

* CSV import/export, UI/UX improvements to import-export interface

* minor styling tweaks

* csv export, clean up export type branching

* abstract domain block entry validation

* foundation for PSL check + suggestions

* Squashed commit of the following:

commit e3655ba4fbea1d55738b2f9e407d3378af26afe6
Author: f0x <f0x@cthu.lu>
Date:   Tue Jan 31 15:19:10 2023 +0100

    let debug depend on env (prod/debug) again

commit 79c792b832a2b59e472dcdff646bad6d71b42cc9
Author: f0x <f0x@cthu.lu>
Date:   Tue Jan 31 00:34:01 2023 +0100

    update checklist components

commit 4367960fe4be4e3978077af06e63a729d64e32fb
Author: f0x <f0x@cthu.lu>
Date:   Mon Jan 30 23:46:20 2023 +0100

    checklist performance improvements

commit 204a4c02d16ffad189a6e8a6001d5bf4ff95fc4e
Author: f0x <f0x@cthu.lu>
Date:   Mon Jan 30 20:05:34 2023 +0100

    checklist field: use reducer for state

* remove debug logging

* show and use domain block suggestion

* restructure import/export buttons

* updating suggestions

* suggestion overview

* restructure check-list behavior, domain import/export
2023-02-03 12:07:40 +01:00
Autumn! 49beb17a8f
[chore] Text formatting overhaul (#1406)
* Implement goldmark debug print for hashtags and mentions

* Minify HTML in FromPlain

* Convert plaintext status parser to goldmark

* Move mention/tag/emoji finding logic into formatter

* Combine mention and hashtag boundary characters

* Normalize unicode when rendering hashtags
2023-02-03 11:58:58 +01:00
tobi 271da016b9
[bugfix] Read Bookwyrm Articles more thoroughly (#1410) 2023-02-02 16:41:02 +01:00
tobi 382512a5a6
[feature] Implement /api/v2/instance endpoint (#1409)
* interim: start adding /api/v2/instance

* finish up
2023-02-02 14:08:13 +01:00
tobi 4ee4cd2da1
[chore/performance] use only 1 sqlite db connection regardless of multiplier (#1408) 2023-02-01 11:55:34 +01:00
tobi b80be48fed
[chore] Use 'immediate' lock for sqlite transactions (#1404)
* [chore] Use 'immediate' lock for sqlite transactions

* allow 1 connection regardless of cpu amount
2023-01-31 13:46:45 +01:00
Daniele Sluijters eccb3800d0
[chore] Silence maxprocs logging (#1402)
This switches the logger to Debug. By default the library logs things
internally despite returning errors. Due to the way we had it hooked up
this resulted in scary error level logs being emitted for innocuous
errors. Now those errors will only be visible in debug mode.

Fixes: #1398
Relates to: #1336
2023-01-31 09:39:46 +01:00
ketan-vijayvargiya dc766f9e6f
[docs] Add an example on how to setup redirect with Traefik (#1395) 2023-01-30 10:47:03 +01:00
dependabot[bot] 356e238793
[chore]: Bump github.com/go-playground/validator/v10 (#1400)
Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.11.1 to 10.11.2.
- [Release notes](https://github.com/go-playground/validator/releases)
- [Commits](https://github.com/go-playground/validator/compare/v10.11.1...v10.11.2)

---
updated-dependencies:
- dependency-name: github.com/go-playground/validator/v10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 10:45:34 +01:00
dependabot[bot] 7bcdf35cc1
[chore]: Bump github.com/microcosm-cc/bluemonday from 1.0.21 to 1.0.22 (#1399)
Bumps [github.com/microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday) from 1.0.21 to 1.0.22.
- [Release notes](https://github.com/microcosm-cc/bluemonday/releases)
- [Commits](https://github.com/microcosm-cc/bluemonday/compare/v1.0.21...v1.0.22)

---
updated-dependencies:
- dependency-name: github.com/microcosm-cc/bluemonday
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-30 10:45:19 +01:00
Mina Galić 43cbe3b45c
[docs] Simplify Apache httpd proxy documentation (#1396)
since 2.4.47 (released April 22nd 2021), Apache httpd can ProxyPass to
websockets on the same URL, without mod_rewrite (and, without
mod_proxy_wstunnel).
2023-01-30 10:45:01 +01:00
tobi 3283900b0d
[feature] Federate reports to remote instance as Flag (if desired) (#1386)
* reports federate out, we did it lxds

* fix optional line start (should be optional slash)
2023-01-27 14:48:11 +01:00
tobi c59ec6f2a4
[docs] Add Flag documentation to federation docs (#1393) 2023-01-27 14:39:28 +01:00
tobi 1fa574f148
[docs] Tidy up federation docs into 'federating with gotosocial' section (#1392) 2023-01-27 12:32:23 +01:00
tobi 8d18888db6
[chore/docs] add instance-expose-suspended-web to instance docs (#1391) 2023-01-27 09:23:54 +01:00
f0x52 08f8feaec5
[feature/frontend] filterable local emoji list (#1385) 2023-01-27 09:09:26 +01:00
tobi 782169da76
[chore] set max open / idle conns + conn max lifetime for both postgres and sqlite (#1369)
* [chore] set max open / idle conns + conn max lifetime for both postgres and sqlite

* reduce cache size default to 8MiB, reduce connections to 2 * cpu

* introduce max open conns multiplier, tune sqlite and pg separately

* go fmt
2023-01-26 15:12:48 +01:00
f0x52 17eecfb6d9
[feature] Public list of suspended domains (#1362)
* basic rendered domain blocklist (unauthenticated!)

* style basic domain block list

* better formatting for domain blocklist

* add opt-in config option for showing suspended domains

* format/linter

* re-use InstancePeersGet for web-accessible domain blocklist

* reword explanation, border styling

* always attach blocklist handler, update error message

* domain blocklist error message grammar
2023-01-25 18:06:41 +01:00
tobi 993aae5e48
[feature] Accept incoming federated Flag activity (#1382)
* start working on handling incoming Flag activity

* interim commit

* federate Flag in successfully
2023-01-25 11:12:27 +01:00
tobi faeb7ded3b
[feature] Implement reports admin API so admins can view + close reports (#1378)
* add admin report api endpoints + tests

* [chore] remove funky duplicate attachment in testrig
2023-01-25 11:12:17 +01:00
f0x52 27d4e364e0
[chore] Settings refactor fix4 (#1383)
* fix error handling behavior in emoji overview and FormWithData components

* css: long domain cutoff

* unused require

* eslint vscode task
2023-01-25 09:47:55 +01:00
tobi 36f62d6e60
[chore] remove funky duplicate attachment in testrig (#1379)
* [chore] remove funky duplicate attachment in testrig

* whoops
2023-01-23 13:39:01 +01:00
tobi e9747247d5
[feature] Implement /api/v1/reports endpoints on client API (#1330)
* start adding report client api

* route + test reports get

* start report create endpoint

* you can create reports now babyy

* stub account report processor

* add single reportGet endpoint

* fix test

* add more filtering params to /api/v1/reports GET

* update swagger

* use marshalIndent in tests

* add + test missing Link info
2023-01-23 13:14:21 +01:00
tobi 605dfca1af
[chore] bump go version to 1.19.5 (#1377) 2023-01-23 11:58:58 +01:00
dependabot[bot] 98a09b5633
[chore]: Bump github.com/spf13/viper from 1.14.0 to 1.15.0 (#1375)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 10:24:00 +01:00
dependabot[bot] 3e4dc6bff3
[chore]: Bump github.com/abema/go-mp4 from 0.9.0 to 0.10.0 (#1374)
Bumps [github.com/abema/go-mp4](https://github.com/abema/go-mp4) from 0.9.0 to 0.10.0.
- [Release notes](https://github.com/abema/go-mp4/releases)
- [Commits](https://github.com/abema/go-mp4/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: github.com/abema/go-mp4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-23 10:23:29 +01:00
Kelson Vibber 73be24401a
[feature] Add RSS autodiscovery on profiles that enable RSS (#1373) 2023-01-23 10:23:07 +01:00
즈눅 13ec15d2bb
[chore] extending maximumPasswordLength to 256 (#1372)
* [chore] extending maximumPasswordLength to 256

Resolves: #1365

* Make long test longer
2023-01-22 23:25:11 +01:00
tobi 0ceacd7b1d
[chore] bump db dependencies (#1366) 2023-01-22 12:26:47 +01:00
f0x52 b375d3b5d6
[chore] Add name to instance field for autosuggestion (#1359) 2023-01-19 17:37:42 +01:00
f0x52 747683ba54
[chore] Settings refactor fix 2 (#1357)
* fix emoji query tagging

* fix proxy url for gts instance

* fix: don't flash callback error on authorize flow
2023-01-18 16:41:00 +01:00
f0x52 13e3aaaed1
[chore] Fix new emoji preview title/alt text (#1354)
* fix new emoji preview title/alt text

* empty commit to start Drone pr build
2023-01-18 15:16:29 +01:00
f0x52 9b139b6320
[frogend] Settings refactor (#1318)
* yakshave new form field structure

* fully refactor user profile settings form

* use rtk query api for profile settings

* refactor user post settings

* refactor password change form

* refactor admin settings

* FormWithData structure for user forms

* admin actions refactor

* whitespace

* fix user settings data prop

* remove superfluous logging

* cleanup old code

* refactor federation/suspend (overview, detail)

* mostly abstracted (emoji) checkbox list

* refactor parse-from-toot

* refactor custom-emoji, progress on federation bulk

* loading icon styling to prevent big spinny

* refactor federation import-export interface

* cleanup old files

* [chore] Update/add license headers for 2023

* redux fixes

* text-field exports

* appease the linter

* refactor authentication with RTK Query

* fix login/logout state transition weirdness

* fixes/cleanup

* small linter-related fixes

* add eslint license header check, fix existing files

* remove old code, clarify comment

* clarify suspend on subdomains

* collapse if/else

* fa-fw width info comment
2023-01-18 14:45:14 +01:00
tobi 974ec80a20
[chore] Change default sqlite busy timeout to 5m (#1352) 2023-01-18 14:37:52 +01:00
Daniele Sluijters acc333c40b
[feature] Inherit resource limits from cgroups (#1336)
When GTS is running in a container runtime which has configured CPU or
memory limits or under an init system that uses cgroups to impose CPU
and memory limits the values the Go runtime sees for GOMAXPROCS and
GOMEMLIMIT are still based on the host resources, not the cgroup.

At least for the throttling middlewares which use GOMAXPROCS to
configure their queue size, this can result in GTS running with values
too big compared to the resources that will actuall be available to it.

This introduces 2 dependencies which can pick up resource contraints
from the current cgroup and tune the Go runtime accordingly. This should
result in the different queues being appropriately sized and in general
more predictable performance. These dependencies are a no-op on
non-Linux systems or if running in a cgroup that doesn't set a limit on
CPU or memory.

The automatic tuning of GOMEMLIMIT can be disabled by either explicitly
setting GOMEMLIMIT yourself or by setting AUTOMEMLIMIT=off. The
automatic tuning of GOMAXPROCS can similarly be counteracted by setting
GOMAXPROCS yourself.
2023-01-17 20:59:04 +00:00
tobi 627b8eeae6
[feature] Tune sqlite pragmas (#1349)
* sqlite pragma tuning

* use formatuint

* add sqlite busy timeout

* fix incorrect cache size format

* update envparsing test

* add sqlite tuning flags to cli

* set sqlite timeout to 30s default
2023-01-17 12:29:44 +00:00
dependabot[bot] a6c6bdb34a
[chore]: Bump codeberg.org/gruf/go-errors/v2 from 2.0.2 to 2.1.1 (#1346)
Bumps codeberg.org/gruf/go-errors/v2 from 2.0.2 to 2.1.1.

---
updated-dependencies:
- dependency-name: codeberg.org/gruf/go-errors/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-17 11:25:13 +00:00
tobi d4cddf460a
[bugfix] Parse video metadata more accurately; allow Range in fileserver (#1342)
* don't serve unused fields for video attachments

* parse video bitrate + duration more accurately

* use ServeContent where appropriate to respect Range

* abstract temp file seeker into its own function
2023-01-16 16:19:17 +01:00
dependabot[bot] fe3e9ede52
[chore]: Bump github.com/minio/minio-go/v7 from 7.0.44 to 7.0.47 (#1348)
Bumps [github.com/minio/minio-go/v7](https://github.com/minio/minio-go) from 7.0.44 to 7.0.47.
- [Release notes](https://github.com/minio/minio-go/releases)
- [Commits](https://github.com/minio/minio-go/compare/v7.0.44...v7.0.47)

---
updated-dependencies:
- dependency-name: github.com/minio/minio-go/v7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 10:29:47 +01:00
dependabot[bot] 2a46980082
[chore]: Bump golang.org/x/oauth2 from 0.3.0 to 0.4.0 (#1347)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 10:29:19 +01:00
Phil Hagelberg 6b15b83bf1
[docs] Remove videos from the list of missing features in the FAQ. (#1344)
These actually work now! Yay.
2023-01-16 10:28:18 +01:00
tobi 132c73883f
[bugfix] Mount bookmarks endpoint correctly (#1338) 2023-01-13 17:07:52 +01:00
tobi eafd73c292
[chore] Remove omitempty on account source; refactor tests to use prettyprint json (#1337)
* remove omitEmpty tag on account source items

* update tests
2023-01-13 17:02:45 +01:00
kim 5318054808
[performance] media processing improvements (#1288)
* media processor consolidation and reformatting, reduce amount of required syscalls

Signed-off-by: kim <grufwub@gmail.com>

* update go-store library, stream jpeg/png encoding + use buffer pools, improved media processing AlreadyExists error handling

Signed-off-by: kim <grufwub@gmail.com>

* fix duration not being set, fix mp4 test expecting error

Signed-off-by: kim <grufwub@gmail.com>

* fix test expecting media files with different extension

Signed-off-by: kim <grufwub@gmail.com>

* remove unused code

Signed-off-by: kim <grufwub@gmail.com>

* fix expected storage paths in tests, update expected test thumbnails

Signed-off-by: kim <grufwub@gmail.com>

* remove dead code

Signed-off-by: kim <grufwub@gmail.com>

* fix cached presigned s3 url fetching

Signed-off-by: kim <grufwub@gmail.com>

* fix tests

Signed-off-by: kim <grufwub@gmail.com>

* fix test models

Signed-off-by: kim <grufwub@gmail.com>

* update media processing to use sync.Once{} for concurrency protection

Signed-off-by: kim <grufwub@gmail.com>

* shutup linter

Signed-off-by: kim <grufwub@gmail.com>

* fix passing in KVStore GetStream() as stream to PutStream()

Signed-off-by: kim <grufwub@gmail.com>

* fix unlocks of storage keys

Signed-off-by: kim <grufwub@gmail.com>

* whoops, return the error...

Signed-off-by: kim <grufwub@gmail.com>

* pour one out for tobi's code <3

Signed-off-by: kim <grufwub@gmail.com>

* add back the byte slurping code

Signed-off-by: kim <grufwub@gmail.com>

* check for both ErrUnexpectedEOF and EOF

Signed-off-by: kim <grufwub@gmail.com>

* add back links to file format header information

Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2023-01-11 12:13:13 +01:00
Sleep 3512325e46
[feature] Add local user and post count to nodeinfo responses (#1325)
* Add local user and post count to nodeinfo responses

This fixes #1307 (at least partially). The nodeinfo endpoint should now
return the total users on an instance, along with their post count.

* Update NodeInfoUsers docstring and swagger yaml file
2023-01-11 11:36:36 +01:00
tobi d6487933c7
[feature] Implement Report database model and utility functions (#1310)
* implement report database model

* implement report cache + config changes

* implement report database functions

* report uri / regex functions

* update envparsing test

* remove unnecessary uri index

* remove unused function + cache lookup

* process error when storing report
2023-01-10 14:19:05 +00:00
dependabot[bot] 36aa6854bd
[chore] Bump json5 from 1.0.1 to 1.0.2 in /web/source (#1308)
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 10:24:49 +01:00
dependabot[bot] ac562fa79e
[chore]: Bump github.com/coreos/go-oidc/v3 from 3.4.0 to 3.5.0 (#1322)
Bumps [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/coreos/go-oidc/releases)
- [Commits](https://github.com/coreos/go-oidc/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: github.com/coreos/go-oidc/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 08:23:49 +00:00
dependabot[bot] 0ca6a9d868
[chore]: Bump golang.org/x/image from 0.2.0 to 0.3.0 (#1320)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.2.0 to 0.3.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 08:21:58 +00:00
dependabot[bot] 86ae0b142b
[chore]: Bump golang.org/x/text from 0.5.0 to 0.6.0 (#1321)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 08:11:42 +00:00
dependabot[bot] 345b765a46
[chore]: Bump golang.org/x/net from 0.4.0 to 0.5.0 (#1319)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 08:10:55 +00:00
kim 1bda6a2002
[bugfix] return early in websocket upgrade handler (#1315)
* launch websocket streaming in goroutine to allow upgrade handler to return

* don't send any message on ping, improved close check on failed read

* use context to signal wsconn close, ensure canceled in read goroutine

Signed-off-by: kim <grufwub@gmail.com>
2023-01-08 11:43:08 +00:00
tobi 98edd75f1b
[docs] Rewrite sponsorship + funding section, add NLnet (#1305)
* [docs] Rewrite sponsorship + funding section, add NLnet

* use just one small nlnet logo
2023-01-08 12:37:10 +01:00
Logan 9859a43b87
[docs] Add s3 ssl variable to storage docs (#1294)
* update storage docs

* add use ssl to example/config.yaml
2023-01-08 12:28:58 +01:00
kim 2bf9bfa24f
[bugfix] fix panic during status delete loop by breaking out early on len(statuses) == 0 (#1317)
Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2023-01-08 11:33:03 +01:00
tobi 67919204af
[chore/frogend] update status blockquote css (#1302)
Current blockquote margin + padding values were causing issues on small screens. This PR updates these values to use horizontal space a bit better!
2023-01-06 16:01:09 +01:00
Anant Shrivastava 2a1205ab32
[docs] AWS S3 config details added (#1300)
* AWS S3 config details added

It was interesting to note that since presigned urls are used buckets dont need to be exposed publically. this was an interesting change compared to other mastodon specific s3 bucket guides hence documented here for correct directions.

* Update storage.md

1. Added AWS identified to make it clear its aws specific.
2. Adjusted text around data migration

* updation as requested

Refining the doc as per request.
2023-01-06 14:32:40 +01:00
kim adbc87700a
[chore] pull in latest go-cache, go-runners versions (#1306)
Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2023-01-06 11:16:09 +01:00
tobi 0dbe6c514f
[chore] Update/add license headers for 2023 (#1304) 2023-01-05 12:43:00 +01:00
tobi ff46dd485a
[chore] Fix emoji notnull constraint on initial gtsmodel (#1303) 2023-01-05 12:37:50 +01:00
f0x52 de74cc6e94
[bugfix/frogend] replace ch units to prevent layout shift on page load (#1301) 2023-01-05 09:38:01 +01:00
tobi 90a14abb0c
[feature] HTTP request throttling middleware (#1297)
* [feature] Add throttling middleware to AP endpoints

* refactor a lil bit

* use config setting, start updating docs

* doc updates

* use relative links in faq doc

* small docs fixes

* return code 503 instead of 429 when throttled

* throttle other endpoints too

* simplify token channel prefills
2023-01-04 11:57:59 +01:00
Brian Clemens 0b8eafec5c
[docs] Fix documentation edit link (#1298) 2023-01-04 10:39:26 +01:00
kim 71dfea7e47
[chore] shuffle middleware to split rate limitting into client/s2s/fileserver, share gzip middleware globally (#1290)
Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2023-01-03 11:50:59 +01:00
Alex Schroeder 9ecb1c8aa5
[docs] Add troubleshooting section for Apache (#1291) 2023-01-03 11:13:52 +01:00
tobi 941893a774
[chore] The Big Middleware and API Refactor (tm) (#1250)
* interim commit: start refactoring middlewares into package under router

* another interim commit, this is becoming a big job

* another fucking massive interim commit

* refactor bookmarks to new style

* ambassador, wiz zeze commits you are spoiling uz

* she compiles, we're getting there

* we're just normal men; we're just innocent men

* apiutil

* whoopsie

* i'm glad noone reads commit msgs haha :blob_sweat:

* use that weirdo go-bytesize library for maxMultipartMemory

* fix media module paths
2023-01-02 12:10:50 +00:00
dependabot[bot] 560ff1209d
[chore]: Bump github.com/abema/go-mp4 from 0.8.0 to 0.9.0 (#1287)
Bumps [github.com/abema/go-mp4](https://github.com/abema/go-mp4) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/abema/go-mp4/releases)
- [Commits](https://github.com/abema/go-mp4/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: github.com/abema/go-mp4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-02 12:10:35 +00:00
dependabot[bot] b966d3b157
[chore]: Bump github.com/gin-gonic/gin from 1.8.1 to 1.8.2 (#1286)
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/gin-gonic/gin/releases)
- [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gin-gonic/gin/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/gin-gonic/gin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-27 08:29:42 +00:00
dependabot[bot] abd594b71f
[chore]: Bump codeberg.org/gruf/go-bytesize from 1.0.0 to 1.0.2 (#1285)
Bumps codeberg.org/gruf/go-bytesize from 1.0.0 to 1.0.2.

---
updated-dependencies:
- dependency-name: codeberg.org/gruf/go-bytesize
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-27 08:28:44 +00:00
tobi 1659f75ae6
[feature] For video attachments, store + return fps, bitrate, duration (#1282)
* start messing about with different mp4 metadata extraction

* heyyooo it works

* add test cow

* move useful multierror to gtserror package

* error out if video doesn't seem to be a real mp4

* test parsing mkv in disguise as mp4

* tidy up error handling

* remove extraneous line

* update framerate formatting

* use float32 for aspect

* fixy mctesterson
2022-12-22 11:48:28 +01:00
tobi eabb906268
[bugfix] fix media create error not being checked (#1283) 2022-12-21 17:52:07 +01:00
tobi 6ebdc306ed
[bugfix] Close reader gracefully when streaming recache of remote media to fileserver api caller (#1281)
* close pipereader on failed data function

* gently slurp the bytes

* readability updates

* go fmt

* tidy up file server tests + add more cases

* start moving io wrappers to separate iotools package. Remove use of buffering while piping recache stream

Signed-off-by: kim <grufwub@gmail.com>

* add license text

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: kim <grufwub@gmail.com>
2022-12-21 11:17:43 +01:00
tobi 0871f5d181
[chore] note broken go v1.19.4 in contributing.md (#1278) 2022-12-17 10:20:48 +00:00
tobi 2bbc64be43
[feature] Enable basic video support (mp4 only) (#1274)
* [feature] basic video support

* fix missing semicolon

* replace text shadow with stacked icons

Co-authored-by: f0x <f0x@cthu.lu>
2022-12-17 04:38:56 +00:00
tobi 0f38e7c9b0
[chore] fix some little config whoopsies (#1272) 2022-12-16 22:38:41 +00:00
kim da751c02fb
update go-cache to v3.2.0 with support for ignoring errors (#1273) 2022-12-16 22:36:52 +00:00
Autumn! eb08529f35
[chore/bugfix] Switch markdown from blackfriday to goldmark (#1267)
Co-authored-by: Autumn! <autumnull@posteo.net>
2022-12-16 12:20:22 +01:00
f0x52 2b0342b231
[bugfix] use match-sorter for filtering domain blocks (#1270) 2022-12-16 12:19:58 +01:00
tobi 1d24c1c283
[bugfix] Use null for empty api status language (#1268)
* [bugfix] Use null for empty api status `language`

* update swagger docs
2022-12-15 09:41:49 +01:00
EchedeyLR bae73982f7
[docs] Update Apache docs to use 127.0.0.1 instead of localhost (#1266)
* Update Apache docs to use 127.0.0.1 instead

* Update apache-httpd.md
2022-12-15 07:47:48 +01:00
tobi 0f8d938801
[chore] Add svg version of sloth logo as logo.svg (#1265) 2022-12-14 16:08:16 +01:00
tobi 418bfbf494
[docs] Update nginx docs to use 127.0.0.1 instead of localhost (#1264)
Lots of these were appearing:

```
*459 connect() failed (111: Connection refused) while connecting to upstream
```

This change resolves it, see https://stackoverflow.com/a/52550758
2022-12-14 16:07:03 +01:00
Matthew Phillips d10388cc28
[feature] support Sec-Websocket-Protocol in streaming API (#1254)
* [feature] support Sec-Websocket-Protocol in streaming API

* Fix lint problem

* Update based on reviews
2022-12-14 10:56:42 +01:00
kim 69dd5fed2c
[feature] domain block wildcarding (#1178)
* for domain block lookups, lookup along subdomain parts

Signed-off-by: kim <grufwub@gmail.com>

* only lookup up to a max of 5 domain parts to prevent DOS, limit inserted domains to max of 5 subdomains

Signed-off-by: kim <grufwub@gmail.com>

* add test for domain block wildcarding

Signed-off-by: kim <grufwub@gmail.com>

* check cached status first, increase cached domain time

Signed-off-by: kim <grufwub@gmail.com>

* fix domain wildcard part building logic

Signed-off-by: kim <grufwub@gmail.com>

* create separate domain.BlockCache{} type to hold all domain blocks in memory

Signed-off-by: kim <grufwub@gmail.com>

* remove unused variable

Signed-off-by: kim <grufwub@gmail.com>

* add docs and test to domain block cache, check for domain == host in domain block getter funcs

Signed-off-by: kim <grufwub@gmail.com>

* add license text

Signed-off-by: kim <grufwub@gmail.com>

* check order in which we check primary cache

Signed-off-by: kim <grufwub@gmail.com>

* add better documentation of how domain block checking is performed

Signed-off-by: kim <grufwub@gmail.com>

* change

Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2022-12-14 10:55:36 +01:00
Christoph Voigt 8703933df4
[bugfix] fix unordered favorites (#1245)
* [bugfix] fix unordered favorites

* add test for favouritesget

* add license to new test files
2022-12-13 12:33:49 +01:00
kim 58c87bdd7f
[feature] allow uncaching of other media types (#1234)
* simplify pruneRemote, remove unncecessary media trace logging, update RemoteOlderThan() to include headers/avis

Signed-off-by: kim <grufwub@gmail.com>

* cleanup pruneallmeta, add remote header to pruneremote tests

Signed-off-by: kim <grufwub@gmail.com>

* fix olderthan duration additions

Signed-off-by: kim <grufwub@gmail.com>

* fix broken test now that test model header changed

Signed-off-by: kim <grufwub@gmail.com>

* instead use new remote test account for new header model

Signed-off-by: kim <grufwub@gmail.com>

* use newer generated ULID for remote_account_3 to ensure it is sorted last

Signed-off-by: kim <grufwub@gmail.com>

* reorganize serialized keys to match expected test account model order

Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2022-12-12 12:22:19 +01:00
dependabot[bot] a7e71d724c
[chore]: Bump golang.org/x/image from 0.1.0 to 0.2.0 (#1252)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.1.0 to 0.2.0.
- [Release notes](https://github.com/golang/image/releases)
- [Commits](https://github.com/golang/image/compare/v0.1.0...v0.2.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 11:55:18 +01:00
f0x52 4b8d7bd952
[frogend] Emoji copy "Steal this look" (#1222)
* split emoji into local and remote, allow looking up remote emoji by toot url

* optimize some/all filtering

* fix local emoji routes

* implement copy action

* shortcode validation, don't wipe form on error

* copy & disable PATCH

* remove local toot acceptance for testing

* unused import

* parse emoji from account and status, get web_url from status uri

* fix url parse

* submit button loading info

* actually send category

* code cleanup, distinguish between account and status responses

* use loading icons

* fix loading icon on federation page

* require Loading element

* remove unused require

* query explanation, small accessibility tweaks
2022-12-11 16:00:23 +01:00
Daniele Sluijters ce615b5d59
[docs] Serve static assets with nginx (#1251)
* [docs] Serve static assets with nginx

This explains how to use nginx to serve static assets and offload GTS
from that responsibility. It also shows how to have nginx add caching
headers to indicate to clients how long they may cache an asset.

* [docs] Move additional nginx config to advanced

This moves a bunch of additional nginx configuration into the Advanced
page instead. It declutters the nginx configuration page.
2022-12-11 14:18:39 +01:00
kim cb2b2fd805
[feature] support configuring database caches (#1246)
* update config generator to support nested structs, add cache configuration options

* update envparsing test

* add cache configuration to config parse tests

* set cache configuration in testrig

* move caches to sub-cache "gts" namespace, update envparsing, add cache config docs to example config

Signed-off-by: kim <grufwub@gmail.com>
2022-12-11 13:03:15 +00:00
Daniele Sluijters d2a09c1e0b
[docs] Caching webfinger with nginx (#1242)
This explains how nginx can be used to cache webfinger responses and
potentially serve stale responses in case GTS is down. This can be
useful to do in order to ensure webfinger keeps working even if you're
doing some maintenance.
2022-12-11 11:51:07 +01:00
tobi 5e060d0bcb
[feature] Start implementing refetch of lost media files via /api/v1/admin/media_refetch (#1221)
* [chore] Move ShortcodeDomain to its own little util func

* [feature] Add RefetchEmojis function to media manager

* [feature] Expose admin media refresh via admin API

* update following review feedback

- change/fix log levels
- make sure not to try to refetch local emojis
- small style refactoring + comments

* log on emoji refetch start

Signed-off-by: kim <grufwub@gmail.com>
Co-authored-by: kim <grufwub@gmail.com>
2022-12-10 21:43:11 +00:00
tobi 24b4f9b5d7
[chore] make single pull request template (#1239)
When you have multiple templates, they can only be selected by the API, so you can't just open a pull request via the web UI and have the template presented to you. This should fix that by having just one pull request template.
2022-12-09 12:57:07 +01:00
tobi 04636a3ba3
[bugfix] attach bookmarks module to api (#1238) 2022-12-09 12:23:20 +01:00
tobi 610c2708ca
[docs] Update CONTRIBUTING.md, add pull request templates (#1216)
* [docs] Update contributing.md

- Add Pull Request process and guidelines.
- Add feature/bug issue process.
- Rearrange some sections for clarity.
- Add overview of package structure.

* [docs] Add build from source links

* [chore] add pull request templates

These link to the new CONTRIBUTING.md document, and include a checklist to validate that contributors have read the guidelines.

* [docs] Put existing stub CoC in separate doc

* update web related stuff in CONTRIBUTING.md

Co-authored-by: f0x <f0x@cthu.lu>
2022-12-09 11:53:58 +01:00
Christoph Voigt 199672e586
[bugfix] fix unordered favorites (#1236) 2022-12-09 11:46:52 +01:00
Matthew Phillips 477ae50933
[feature] Allow users to create + delete bookbarks, and view bookmarked statuses (#1168)
* Implement Bookmarks

* Update based on review comments

* Update swagger doc

* Fix argument passing to status.Bookmark

* Update changed test

* Updates based on latest PR review
2022-12-09 11:37:12 +01:00
kim e58d2d8122
[chore] move caches to a separate State{} structure (#1078)
* move caches to a separate State{} structure

Signed-off-by: kim <grufwub@gmail.com>

* fix call to log.Panic not using formatted call

Signed-off-by: kim <grufwub@gmail.com>

* move caches to use interfaces, to make switchouts easier in future

Signed-off-by: kim <grufwub@gmail.com>

* fix rebase issue

Signed-off-by: kim <grufwub@gmail.com>

* improve code comment

Signed-off-by: kim <grufwub@gmail.com>

* fix further issues after rebase

Signed-off-by: kim <grufwub@gmail.com>

* heh

Signed-off-by: kim <grufwub@gmail.com>

* add missing license text

Signed-off-by: kim <grufwub@gmail.com>

Signed-off-by: kim <grufwub@gmail.com>
2022-12-08 18:35:14 +01:00
Mike Perham dd1a4cd892
[chore] Remove deprecated linters (#1228) 2022-12-08 12:12:25 +01:00
Marie Axelsson aea16bbf3c
[docs] Update README.md (#1126)
added myself to the team, tyvm.
2022-12-07 21:51:01 +01:00
Andrea 923d333823
[docs] encourage using loopback bind address (#1166) 2022-12-07 21:50:37 +01:00
Dominik Süß 199b685f43
[feature] overhaul the oidc system (#961)
* [feature] overhaul the oidc system

this allows for more flexible username handling and prevents account
takeover using old email addresses

* [feature] add migration path for old OIDC users

* [feature] nicer error reporting for users

* [docs] document the new OIDC flow

* [fix] return early on oidc error

* [docs]: add comments on the finalization logic
2022-12-06 14:15:56 +01:00
Sigrid Solveig Haflínudóttir 1a3f26fb5c
[feature] media: add webp support (#1155)
* media: add webp support

Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>

* bump exif-terminator to v0.5.0

Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>

Signed-off-by: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
2022-12-06 14:15:25 +01:00
f0x52 f9e5ec99bd
[docs] Remove filesystem logging directives from example systemd unit config (#1206)
* remove filesystem logging directives from example systemd unit config

* [docs] Update docs to reflect new systemd config

Co-authored-by: tsmethurst <tobi.smethurst@protonmail.com>
2022-12-05 11:10:13 +01:00
Dominik Süß 611df7b22d
[bugfix]: Prevent extension of S3 presigned url TTL (#1208)
Thanks :)
2022-12-05 11:09:22 +01:00
Daniele Sluijters 847e7c7c3a
[chore] Fix a few possible cases of int truncation (#1207)
This fixes a couple of cases where due to int being platform dependent a
value could get truncated if running on 32bits.
2022-12-04 14:20:41 +01:00
Dominik Süß bc917a4085
[performance]: make s3 urls cacheable (#1194)
Implements #864 and should speed up s3 based installations by a lot.

With more static urls, we can then also implement #1026 for even
better performance when used in conjunction with CDNs
2022-12-02 18:40:49 +00:00
tobi 281f712477
[bugfix] Fix admin account confirm on pre-confirmed account setting email address to empty string (#1203) 2022-12-02 17:41:10 +01:00
tobi 34716d7d7d
[bugfix] Add missing continues in emoji get funcs (#1200) 2022-12-02 16:41:05 +01:00
f0x52 bb7948f31a
[chore/frontend] remove domain block edit functionality until implemented in backend (#1199) 2022-12-02 15:56:23 +01:00
Daniele Sluijters 558b448ab2
[chore] Remove duplicate prefixes from sanitizer (#1195)
In the previous changes that expanded the IPv4 and IPv6 deny lists based
on the IANA registries we inadvertently added a number of duplicates.
This is unnecessary as they're already caught by larger prefixes and
means there's less entries to scan.

This change removes all prefixes that are subnets of other prefixes.
2022-12-01 20:34:55 +01:00
f0x52 85524f8b4b
[bugfix/frontend] fix profile grid scaling in webkit based browsers (#1193) 2022-12-01 17:28:11 +01:00
4193 changed files with 779615 additions and 406172 deletions

View file

@ -12,7 +12,7 @@ steps:
# We use golangci-lint for linting.
# See: https://golangci-lint.run/
- name: lint
image: golangci/golangci-lint:v1.50.1
image: golangci/golangci-lint:v1.53.1
volumes:
- name: go-build-cache
path: /root/.cache/go-build
@ -28,7 +28,7 @@ steps:
- pull_request
- name: test
image: golang:1.19.3-alpine
image: golang:1.20.4-alpine
volumes:
- name: go-build-cache
path: /root/.cache/go-build
@ -44,7 +44,7 @@ steps:
- pull_request
- name: web-setup
image: node:14-alpine
image: node:18-alpine
when:
event:
include:
@ -57,7 +57,7 @@ steps:
- yarn --frozen-lockfile --cache-folder /tmp/cache
- name: web-lint
image: node:14-alpine
image: node:18-alpine
when:
event:
include:
@ -69,7 +69,7 @@ steps:
- yarn run lint
- name: web-build
image: node:14-alpine
image: node:18-alpine
when:
event:
include:
@ -81,7 +81,7 @@ steps:
- yarn run build
- name: snapshot
image: superseriousbusiness/gotosocial-drone-build:0.0.7 # https://github.com/superseriousbusiness/gotosocial-drone-build
image: superseriousbusiness/gotosocial-drone-build:0.2.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
volumes:
- name: go-build-cache
path: /root/.cache/go-build
@ -110,7 +110,7 @@ steps:
- main
- name: release
image: superseriousbusiness/gotosocial-drone-build:0.0.7 # https://github.com/superseriousbusiness/gotosocial-drone-build
image: superseriousbusiness/gotosocial-drone-build:0.2.0 # https://github.com/superseriousbusiness/gotosocial-drone-build
volumes:
- name: go-build-cache
path: /root/.cache/go-build
@ -169,7 +169,7 @@ clone:
steps:
- name: mirror
image: superseriousbusiness/gotosocial-drone-build:0.0.7
image: superseriousbusiness/gotosocial-drone-build:0.2.0
environment:
ORIGIN_REPO: https://github.com/superseriousbusiness/gotosocial
TARGET_REPO: https://codeberg.org/superseriousbusiness/gotosocial
@ -182,6 +182,6 @@ steps:
---
kind: signature
hmac: 46dd4ce5b5dab76bc64c68f4730663ed0ada81471ffcbfa1bcf935d8e7f6a155
hmac: 946c2ffd4e79de07a767ec06ebac0a8ca70a03ce5666aae093c9b0af455041d1
...

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
/vendor/ linguist-generated

View file

@ -0,0 +1,67 @@
name: Frontend Bug Report
description: Report an issue related to the web frontend
title: "[bug] Issue Title"
labels: ["bug", "frontend"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please be cautious with the sensitive information/logs while filing the issue.
- type: textarea
id: desc
attributes:
label: Describe the bug with a clear and concise description of what the bug is. Please include screenshots of any visual issues.
validations:
required: true
- type: input
id: GoToSocial-Version
attributes:
label: What's your GoToSocial Version?
description: Enter the Version of your GoToSocial Installation
placeholder: e.g. v0.3.4
validations:
required: true
- type: input
id: Browser-Version
attributes:
label: Browser version
description: What browser(s) and versions are you using that show this bug?
placeholder: Firefox 103.0b9 (64-bit)
validations:
required: true
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Enter exactly what happened.
validations:
required: false
- type: textarea
id: what-expected
attributes:
label: What you expected to happen?
description: Enter what you expected to happen.
validations:
required: false
- type: textarea
id: how-to-reproduce
attributes:
label: How to reproduce it?
description: As minimally and precisely as possible.
validations:
required: false
- type: textarea
id: anything-else
attributes:
label: Anything else we need to know?
validations:
required: false

View file

@ -2,13 +2,23 @@ name: Bug Report
description: Create a report to help us improve
title: "[bug] Issue Title"
labels: [bug]
assignees:
-
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please be cautious with the sensitive information/logs while filing the issue.
- type: markdown
attributes:
value: |
⚠️ If you're reporting an interoperability issue with a **closed source**
ActivityPub/Mastodon client or server, please report the issue to the
developers of that client or server instead. Without access to their
source debugging the issue is difficult for us. Since GoToSocial is
open source, developers of closed source implementations can run a copy
and autonomously debug the issue. We'll gladly address any bugs they
raise with us.
- type: textarea
id: desc
attributes:
@ -34,15 +44,6 @@ body:
validations:
required: false
- type: input
id: Browser-Version
attributes:
label: Browser version
description: If this is a frontend bug, what browser(s) and versions are you using that show this bug?
placeholder: Firefox 103.0b9 (64-bit)
validations:
required: false
- type: textarea
id: what-happened
attributes:

26
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,26 @@
# Description
> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.
This pull request implements xyz or fixes abc.
closes #(issue)
closes #(another issue)
## Checklist
Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`
If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).
- [ ] I/we have read the [GoToSocial contribution guidelines](https://github.com/superseriousbusiness/gotosocial/blob/main/CONTRIBUTING.md).
- [ ] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [ ] I/we have performed a self-review of added code.
- [ ] I/we have written code that is legible and maintainable by others.
- [ ] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [ ] I/we have run tests and they pass locally with the changes.
- [ ] I/we have run `go fmt ./...` and `golangci-lint run`.

3
.gitignore vendored
View file

@ -36,3 +36,6 @@ shell.nix
# ignore config dirs from IDEs
/.idea/
/.fleet/
# ignore cache dir from mkdocs serve
/.cache

View file

@ -14,18 +14,74 @@ run:
linters:
# enable some extra linters, see here for the list: https://golangci-lint.run/usage/linters/
enable:
- contextcheck
- forcetypeassert
- goconst
- gocritic
- gofmt
- goheader
- gosec
- ifshort
- nilerr
- revive
- wastedassign
# https://golangci-lint.run/usage/linters/#linters-configuration
linters-settings:
# https://golangci-lint.run/usage/linters/#goheader
goheader:
template: |-
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
# https://golangci-lint.run/usage/linters/#govet
govet:
disable:
- composites
- composites
# https://golangci-lint.run/usage/linters/#revive
revive:
rules:
# Enable most default rules.
# See: https://github.com/mgechev/revive/blob/master/defaults.toml
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-naming
- name: error-return
- name: error-strings
- name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unreachable-code
# Disable below rules.
- name: redefines-builtin-id
disabled: true # This one is just annoying.
- name: unused-parameter
disabled: true # We often pass parameters to fulfil interfaces.
# https://golangci-lint.run/usage/linters/#staticcheck
staticcheck:
# Enable all checks, but disable SA1012: nil context passing.
# See: https://staticcheck.io/docs/configuration/options/#checks
checks: ["all", "-SA1012"]

View file

@ -24,6 +24,8 @@ builds:
- netgo
- osusergo
- static_build
- kvformat
- timetzdata
env:
- CGO_ENABLED=0
goos:

View file

@ -5,9 +5,13 @@
# Required
version: 2
mkdocs:
configuration: mkdocs.yml
build:
os: "ubuntu-20.04"
tools:
python: "mambaforge-4.10" # https://docs.readthedocs.io/en/stable/guides/conda.html#making-builds-faster-with-mamba
python:
install:
- requirements: docs/requirements.txt
mkdocs:
configuration: "mkdocs.yml"
conda:
environment: "docs/environment.yml"

8
.vscode/launch.json vendored
View file

@ -2,14 +2,18 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"name": "Debug Package",
"type": "go",
"request": "launch",
"mode": "auto",
"mode": "debug",
"program": "${workspaceFolder}/cmd/gotosocial",
"args": [
"testrig", "start"
],
"buildFlags": "-tags='netgo osusergo static_build kvformat debugenv'",
"env": {
"DEBUG": "1",
},
"cwd": "${workspaceFolder}"
}
]

View file

@ -2,5 +2,11 @@
"go.lintTool":"golangci-lint",
"go.lintFlags": [
"--fast"
]
],
"go.vetFlags": [
"-composites=false ."
],
"eslint.workingDirectories": ["web/source"],
"eslint.lintTask.enable": true,
"eslint.lintTask.options": "${workspaceFolder}/web/source"
}

9
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,9 @@
# Code of Conduct
This document is currently a stub.
In lieu of a fuller code of conduct, here are a few ground rules.
1. We *DO NOT ACCEPT* PRs from right-wingers, Nazis, transphobes, homophobes, racists, harassers, abusers, white-supremacists, misogynists, tech-bros of questionable ethics. If that's you, politely fuck off somewhere else.
2. Any PR that moves GoToSocial in the direction of surveillance capitalism or other bad fediverse behavior will be rejected.
3. Don't spam the general chat too hard.

View file

@ -1,92 +1,116 @@
# Contributing <!-- omit in toc -->
# Contribution Guidelines <!-- omit in toc -->
Hey! Welcome to the CONTRIBUTING.md for GoToSocial :) Thanks for taking a look, that kicks ass.
This document will expand as the project expands, so for now, this is basically a stub.
These contribution guidelines were adapted from / inspired by those of Gitea (https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md). Thanks Gitea!
Contributions are welcome at this point, since the API is fairly stable now and the structure is somewhat coherent.
## Table of Contents <!-- omit in toc -->
Check the [issues](https://github.com/superseriousbusiness/gotosocial/issues) to see if there's anything you fancy jumping in on.
## Table Of Contents <!-- omit in toc -->
- [Communications](#communications)
- [Code of Conduct](#code-of-conduct)
- [Setting up your development environment](#setting-up-your-development-environment)
- [Stylesheet / Web dev](#stylesheet--web-dev)
- [Introduction](#introduction)
- [Bug reports and feature requests](#bug-reports-and-feature-requests)
- [Pull requests](#pull-requests)
- [Code](#code)
- [Documentation](#documentation)
- [Development](#development)
- [Golang forking quirks](#golang-forking-quirks)
- [Setting up your test environment](#setting-up-your-test-environment)
- [Standalone Testrig with Pinafore](#standalone-testrig-with-pinafore)
- [Running automated tests](#running-automated-tests)
- [SQLite](#sqlite)
- [Postgres](#postgres)
- [Both](#both)
- [CLI Tests](#cli-tests)
- [Project Structure](#project-structure)
- [Style](#style)
- [Linting and Formatting](#linting-and-formatting)
- [Updating Swagger docs](#updating-swagger-docs)
- [CI/CD configuration](#cicd-configuration)
- [Release Checklist](#release-checklist)
- [What if something goes wrong?](#what-if-something-goes-wrong)
- [Building Docker containers](#building-docker-containers)
- [With GoReleaser](#with-goreleaser)
- [Manually](#manually)
- [Financial Compensation](#financial-compensation)
- [Building GoToSocial](#building-gotosocial)
- [Binary](#binary)
- [Docker](#docker)
- [With GoReleaser](#with-goreleaser)
- [Manually](#manually)
- [Stylesheet / Web dev](#stylesheet--web-dev)
- [Live Reloading](#live-reloading)
- [Project Structure](#project-structure)
- [Finding your way around the code](#finding-your-way-around-the-code)
- [Style / Linting / Formatting](#style--linting--formatting)
- [Testing](#testing)
- [Standalone Testrig with Semaphore](#standalone-testrig-with-semaphore)
- [Running automated tests](#running-automated-tests)
- [SQLite](#sqlite)
- [Postgres](#postgres)
- [CLI Tests](#cli-tests)
- [Federation](#federation)
- [Updating Swagger docs](#updating-swagger-docs)
- [CI/CD configuration](#cicd-configuration)
- [Release Checklist](#release-checklist)
- [What if something goes wrong?](#what-if-something-goes-wrong)
## Communications
## Introduction
Before starting on something, please comment on an issue to say that you're working on it, and/or drop into the GoToSocial Matrix room [here](https://matrix.to/#/#gotosocial:superseriousbusiness.org).
This document contains important information that will help you to write a successful contribution to GoToSocial. Please read it carefully before opening a pull request!
This is the recommended way of keeping in touch with other developers, asking direct questions about code, and letting everyone know what you're up to.
## Bug reports and feature requests
## Code of Conduct
Currently, we use Github's issue system for tracking bug reports and feature requests.
In lieu of a fuller code of conduct, here are a few ground rules.
You can view all open issues [here](https://github.com/superseriousbusiness/gotosocial/issues "The Github Issues page for GoToSocial").
1. We *DO NOT ACCEPT* PRs from right-wingers, Nazis, transphobes, homophobes, racists, harassers, abusers, white-supremacists, misogynists, tech-bros of questionable ethics. If that's you, politely fuck off somewhere else.
2. Any PR that moves GoToSocial in the direction of surveillance capitalism or other bad fediverse behavior will be rejected.
3. Don't spam the general chat too hard.
Before opening a new issue, whether bug or feature request, **please search carefully through both open and closed issues to make sure it hasn't been addressed already**. You can use Github's keyword issue search for this. If your issue is a duplicate of an existing issue, it will be closed.
## Setting up your development environment
Before you open a feature request issue, please consider the following:
To get started, you first need to have Go installed. GtS is currently using Go 1.19, so you should take that too. See [here](https://golang.org/doc/install).
- Does this feature fit within the scope of GoToSocial? Since we are a small team, we are wary of [feature creep](https://en.wikipedia.org/wiki/Feature_creep "Wikipedia article on Feature Creep"), which can cause maintenance issues.
- Will this feature be generally useful for many users of the software, or is it handy for only a very specific use case?
- Will this feature have a negative impact on the performance of the software? If so, is the tradeoff worth it?
- Does this feature require loosening API security restrictions in some way? If so, it will need a good justification.
- Does this feature belong in GoToSocial's server backend, or is it something that a client could implement instead?
Once you've got go installed, clone this repository into your Go path. Normally, this should be `~/go/src/github.com/superseriousbusiness/gotosocial`.
We tend to prioritize feature requests related to accessibility, fedi interoperability, and client compatibility.
Once that's done, you can try building the project: `./scripts/build.sh`. This will build the `gotosocial` binary.
## Pull requests
If there are no errors, great, you're good to go!
We welcome pull requests from new and existing contributors, with the following provisos:
For automatic re-compiling during development, you can use [nodemon](https://www.npmjs.com/package/nodemon):
- You have read and agree to our Code of Conduct.
- The pull request addresses an existing issue or bug (please link to the relevant issue in your pull request), or is related to documentation.
- If your pull request introduces significant new code paths, you are willing to do some maintenance work on those code paths, and address bugs. We do not appreciate drive-by pull requests that introduce a significant maintenance burden!
- The pull request is of decent quality. We are a small team and unfortunately we don't have a lot of time to help shepherd pull requests, or help with basic coding questions. If you're unsure, don't bite off more than you can chew: start with a small feature or bugfix for your first PR, and work your way up.
```bash
nodemon -e go --signal SIGTERM --exec "go run ./cmd/gotosocial --host localhost testrig start || exit 1"
```
If you have small questions or comments before/during the pull request process, you can [join our Matrix space](https://matrix.to/#/#gotosocial-space:superseriousbusiness.org "GoToSocial Matrix space") at `#gotosocial-space:superseriousbusiness.org`.
### Stylesheet / Web dev
Please read the appropriate section below for the kind of pull request you plan to open.
To work with the stylesheet for templates, you need [Node.js](https://nodejs.org/en/download/) and [Yarn](https://classic.yarnpkg.com/en/docs/install).
### Code
To install Yarn dependencies:
To keep things manageable for maintainers, the process for opening pull requests against the GoToSocial repository works roughly as follows:
```bash
yarn install --cwd web/source
```
1. Open an issue for the feature, bug, or issue your pull request will address, or comment on an existing issue to let everyone know you want to work on it.
2. Use the open issue to discuss your design with us, gather feedback, and resolve any concerns about the implementation.
3. Write your code! Make sure all existing tests pass. Add tests where appropriate. Run linters and formatters. Update documentation.
4. Open your pull request. You can do this as a draft, if you want to gather more feedback on code-in-progress.
5. Let us know that your pull request is ready to be reviewed.
6. Wait for review.
7. Address review comments, make changes to the code where appropriate. It's OK to push back on review comments if you have a sensible reason--we're all learning, after all--but please do so with patience and grace.
8. Get your code merged, rejoice!
To recompile bundles:
To make your code easier to review, try to split your pull request into sensibly-sized commits, but don't worry too much about making it totally perfect: we always squash merge anyways.
```bash
BUDO_BUILD=1 node web/source
```
If your pull request ends up being massive, consider splitting it into smaller discrete pull requests to make it easier to review and reason about.
Or you can run live reloading in development. It will start a webserver (ip/port printed in console, default localhost:8081), while also keeping the bundles
up-to-date on disk. You can access the user/admin panels at localhost:8080/user, localhost:8080/admin, or run in tandem with the GoToSocial testrig, which will also
serve the updated bundles from disk.
Make sure your pull request only contains code that's relevant to the feature you're trying to implement, or the bug you're trying to address. Don't include refactors of unrelated parts of the code in your pull request: make a separate PR for that!
``` bash
NODE_ENV=development node web/source
```
If you open a code pull request without following the above process, we may close it and ask you to follow the process instead.
### Documentation
The process for documentation pull requests is a bit looser than the process for code.
If you see something in the documentation that's missing, wrong, or unclear, feel free to open a pull request addressing it; you don't necessarily need to open an issue first, but please explain why you're opening the PR in the PR comment.
We support a [Conda](https://docs.conda.io/en/latest/)-based workflow for hacking, building & publishing the documentation. Here's how you can get started locally:
* Install [`miniconda`](https://docs.conda.io/en/latest/miniconda.html)
* Create your conda environment: `conda env create -f ./docs/environment.yml`
* Activate the environment: `conda activate gotosocial-docs`
* Serve locally: `mkdocs serve`
Then you can visit [localhost:8000](http://127.0.0.1:8000/) in your browser to view.
When adding a new page, you need to include it in the [`mkdocs.yml`](mkdocs.yml) so it shows in the sidebar in the right section.
If you don't use Conda, you can read the `docs/environment.yml` to see which dependencies are required and `pip install` them manually. It's advisable to do this in a virtual environment, which you can create with something like `python3 -m venv /path-to/store-the-venv`. You can then call `/path-to/store-the-venv/bin/pip`, `/path-to/store-the-venv/bin/mkdocs` etc.
## Development
### Golang forking quirks
@ -120,193 +144,29 @@ In case this post disappears, here are the steps (slightly modified):
> `git remote add origin git@github.com/yourgithubname/gotosocial`
>
## Setting up your test environment
### Building GoToSocial
GoToSocial provides a [testrig](https://github.com/superseriousbusiness/gotosocial/tree/main/testrig) with a number of mock packages you can use in integration tests.
#### Binary
One thing that *isn't* mocked is the Database interface because it's just easier to use an in-memory SQLite database than to mock everything out.
To get started, you first need to have Go installed. GtS is currently using Go 1.20, so you should take that too. See [here](https://golang.org/doc/install) for installation instructions.
### Standalone Testrig with Pinafore
Once you've got go installed, clone this repository into your Go path. Normally, this should be `~/go/src/github.com/superseriousbusiness/gotosocial`.
You can launch a testrig as a standalone server running at localhost, which you can connect to using something like [Pinafore](https://github.com/nolanlawson/pinafore).
Once you've installed the prerequisites, you can try building the project: `./scripts/build.sh`. This will build the `gotosocial` binary.
To do this, first build the gotosocial binary with `./scripts/build.sh`.
If there are no errors, great, you're good to go!
Then, launch the testrig by invoking the binary as follows:
For automatic re-compiling during development, you can use [nodemon](https://www.npmjs.com/package/nodemon):
```bash
GTS_DB_TYPE="sqlite" GTS_DB_ADDRESS=":memory:" ./gotosocial --host localhost:8080 testrig start
nodemon -e go --signal SIGTERM --exec "go run ./cmd/gotosocial --host localhost testrig start || exit 1"
```
To run Pinafore locally in dev mode, first clone the [Pinafore](https://github.com/nolanlawson/pinafore) repository, and then run the following command in the cloned directory:
```bash
yarn run dev
```
The Pinafore instance will start running on `localhost:4002`.
To connect to the testrig, navigate to `http://localhost:4002` and enter your instance name as `localhost:8080`.
At the login screen, enter the email address `zork@example.org` and password `password`. You will get a confirmation prompt. Accept, and you are logged in as Zork.
Note the following constraints:
- Since the testrig uses an in-memory database, the database will be destroyed when the testrig is stopped.
- If you stop the testrig and start it again, any tokens or applications you created during your tests will also be removed. As such, you need to log out and in again every time you stop/start the rig.
- The testrig does not make any actual external HTTP calls, so federation will not work from a testrig.
### Running automated tests
There are a few different ways of running tests. Each requires the use of the `-p 1` flag, to indicate that they should not be run in parallel.
#### SQLite
If you would like to run tests as quickly as possible, using an SQLite in-memory database, use:
```bash
GTS_DB_TYPE="sqlite" GTS_DB_ADDRESS=":memory:" go test ./...
```
#### Postgres
If you want to run tests against a Postgres database running on localhost, run:
```bash
GTS_DB_TYPE="postgres" GTS_DB_ADDRESS="localhost" go test -p 1 ./...
```
In the above command, it is assumed you are using the default Postgres password of `postgres`.
#### Both
Finally, to run tests against both database types one after the other, use:
```bash
./scripts/test.sh
```
### CLI Tests
In [./test/envparsing.sh](./test/envparsing.sh) there's a test for making sure that CLI flags, config, and environment variables get parsed as expected.
Although this test *is* part of the CI/CD testing process, you probably won't need to worry too much about running it yourself. That is, unless you're messing about with code inside the `main` package in `cmd/gotosocial`, or inside the `config` package in `internal/config`.
## Project Structure
For project structure, GoToSocial follows a standard and widely accepted project layout [defined here](https://github.com/golang-standards/project-layout). As the author writes:
> This is a basic layout for Go application projects. It's not an official standard defined by the core Go dev team; however, it is a set of common historical and emerging project layout patterns in the Go ecosystem.
Most of the crucial business logic of the application is found inside the various packages and subpackages of the `internal` directory.
Where possible, we prefer more files and packages of shorter length that very clearly pertain to definable chunks of application logic, rather than fewer but longer files: if one `.go` file is pushing 1,000 lines of code, it's probably too long.
## Style
It is a good idea to read the short official [Effective Go](https://golang.org/doc/effective_go) page before submitting code: this document is the foundation of many a style guide, for good reason, and GoToSocial more or less follows its advice.
Another useful style guide that we try to follow: [this one](https://github.com/bahlo/go-styleguide).
In addition, here are some specific highlights from Uber's Go style guide which agree with what we try to do in GtS:
- [Group Similar Declarations](https://github.com/uber-go/guide/blob/master/style.md#group-similar-declarations).
- [Reduce Nesting](https://github.com/uber-go/guide/blob/master/style.md#reduce-nesting).
- [Unnecessary Else](https://github.com/uber-go/guide/blob/master/style.md#unnecessary-else).
- [Local Variable Declarations](https://github.com/uber-go/guide/blob/master/style.md#local-variable-declarations).
- [Reduce Scope of Variables](https://github.com/uber-go/guide/blob/master/style.md#reduce-scope-of-variables).
- [Initializing Structs](https://github.com/uber-go/guide/blob/master/style.md#initializing-structs).
## Linting and Formatting
Before you submit any code, make sure to run `go fmt ./...` to update whitespace and other opinionated formatting.
We use [golangci-lint](https://golangci-lint.run/) for linting, which allows us to catch style inconsistencies and potential bugs or security issues, using static code analysis.
If you make a PR that doesn't pass the linter, it will be rejected. As such, it's good practice to run the linter locally before pushing or opening a PR.
To do this, first install the linter following the instructions [here](https://golangci-lint.run/usage/install/#local-installation).
Then, you can run the linter with:
```bash
golangci-lint run
```
If there's no output, great! It passed :).
## Updating Swagger docs
GoToSocial uses [go-swagger](https://goswagger.io) to generate Swagger API documentation from code annotations.
You can install go-swagger following the instructions [here](https://goswagger.io/install.html).
If you change Swagger annotations on any of the API paths, you can generate a new Swagger file at `./docs/api/swagger.yaml` by running:
```bash
swagger generate spec --scan-models --exclude-deps -o docs/api/swagger.yaml
```
## CI/CD configuration
GoToSocial uses [Drone](https://www.drone.io/) for CI/CD tasks like running tests, linting, and building Docker containers.
These runs are integrated with GitHub, and will be run on opening a pull request or merging into main.
The Drone instance for GoToSocial is [here](https://drone.superseriousbusiness.org/superseriousbusiness/gotosocial).
The `drone.yml` file is [here](./.drone.yml) — this defines how and when Drone should run. Documentation for Drone is [here](https://docs.drone.io/).
It is worth noting that the `drone.yml` file must be signed by the Drone admin account to be considered valid. This must be done every time the file is changed. This is to prevent tampering and hijacking of the Drone instance. See [here](https://docs.drone.io/signature/).
To sign the file, first install and setup the [drone cli tool](https://docs.drone.io/cli/install/). Then, run:
```bash
drone -t PUT_YOUR_DRONE_ADMIN_TOKEN_HERE -s https://drone.superseriousbusiness.org sign superseriousbusiness/gotosocial --save
```
## Release Checklist
First things first: If this is a security hot-fix, we'll probably rush through this list, and make a prettier release a few days later.
Now, with that out of the way, here's our Checklist.
GoToSocial follows [Semantic Versioning](https://semver.org/).
So our first concern on the Checklist is:
- What version are we releasing?
Next we need to check:
- Do the assets have to be rebuilt and committed to the repository.
- Do the swagger docs have to be rebuilt?
On the project management side:
- Are there any issues that have to be moved to a different milestone?
- Are there any things on the [Roadmap](./ROADMAP.md) that can be ticked off?
Once we're happy with our Checklist, we can create the tag, and push it.
And the rest [is automation](./.drone.yml).
We can now head to GitHub, and add some personality to the release notes.
Finally, we make announcements on the all our channels that the release is out!
### What if something goes wrong?
Sometimes things go awry.
We release a buggy release, we forgot something ­ something important.
If the release is so bad that it's unusable ­ or dangerous! ­ to a great part of our user-base, we can pull.
That is: Delete the tag.
Either way, once we've resolved the issue, we just start from the top of this list again. Version numbers are cheap. It's cheap to burn them.
## Building Docker containers
#### Docker
For both of the below methods, you need to have [Docker buildx](https://docs.docker.com/buildx/working-with-buildx/) installed.
### With GoReleaser
##### With GoReleaser
GoToSocial uses the release tooling [GoReleaser](https://goreleaser.com/intro/) to make multiple-architecture + Docker builds simple.
@ -328,7 +188,7 @@ goreleaser --rm-dist --snapshot
If all goes according to plan, you should now have a number of multiple-architecture binaries and tars inside the `./dist` folder, and snapshot Docker images should be built (check your terminal output for version).
### Manually
##### Manually
If you prefer a simple approach to building a Docker container, with fewer dependencies (go-swagger, Node, Yarn), you can also just build in the following way:
@ -358,8 +218,304 @@ See also: [exhaustive list of GOOS and GOARCH values](https://gist.github.com/li
And: [exhaustive list of possible values for docker's `--platform`](https://github.com/tonistiigi/binfmt/#build-test-image)
## Financial Compensation
### Stylesheet / Web dev
Right now, there's no structure in place for financial compensation for pull requests and code. This is simply because there's no money being made on the project, apart from the very small weekly Liberapay donations.
GoToSocial uses Gin templates in the `web/template` folder. Static assets are stored in `web/assets`. Source files for stylesheets and JS bundles (for frontend enhancement, and the settings interface) are stored in `web/source`, and bundled from there to the `web/assets/dist` folder (gitignored).
If money starts coming in, I'll start looking at proper financial structures, but for now, code is considered to be a donation in itself.
To bundle changes, you need [Node.js](https://nodejs.org/en/download/) and [Yarn](https://classic.yarnpkg.com/en/docs/install).
Using [NVM](https://github.com/nvm-sh/nvm) is one convenient way to install them which also supports managing different Node versions.
To install Yarn dependencies:
```bash
yarn install --cwd web/source
```
To recompile bundles:
```bash
node web/source
```
#### Live Reloading
For a more convenient development environment, you can run a livereloading version of the bundler alongside the [testrig](#testing).
Open two terminals, first start the testrig on port 8081:
``` bash
GTS_PORT=8081 go run ./cmd/gotosocial testrig start
```
Then start the bundler, which will run on port 8080, and proxy requests to the testrig instance where needed.
``` bash
NODE_ENV=development node web/source
```
The livereloading bundler *will not* change the bundled assets in `dist/`, so once you are finished with changes and want to deploy it somewhere, you have to run `node web/source` to generate production-ready bundles.
### Project Structure
For project structure, GoToSocial follows a standard and widely accepted project layout [defined here](https://github.com/golang-standards/project-layout). As the author writes:
> This is a basic layout for Go application projects. It's not an official standard defined by the core Go dev team; however, it is a set of common historical and emerging project layout patterns in the Go ecosystem.
Where possible, we prefer more files and packages of shorter length that very clearly pertain to definable chunks of application logic, rather than fewer but longer files: if one `.go` file is pushing 1,000 lines of code, it's probably too long.
#### Finding your way around the code
Most of the crucial business logic of the application is found inside the various packages and subpackages of the `internal` directory. Here's a brief summary of each of these:
`internal/ap` - ActivityPub utility functions and interfaces.
`internal/api` - Models, routers, and utilities for the client and federated (ActivityPub) APIs. This is where routes are attached to the router, and where you want to be if you're adding a route.
`internal/concurrency` - Worker models used by the processor and other queues.
`internal/config` - Code for configuration flags, CLI flag parsing, and getting/setting config.
`internal/db` - DB interfaces for interacting with sqlite/postgres databases. Database migration code is in `internal/db/bundb/migrations`.
`internal/email` - Email functionality, email sending via SMTP.
`internal/federation` - ActivityPub federation code; implements `go-fed` interfaces.
`internal/federation/federatingdb` - Implementation of `go-fed`'s Database interface.
`internal/federation/dereferencing` - Code for making http calls to fetch resources from remote instances.
`internal/gotosocial` - GoToSocial server startup/shutdown logic.
`internal/gtserror` - Error models.
`internal/gtsmodel` - Database and internal models. This is where `bundb` annotations live.
`internal/httpclient` - The HTTP client used by GoToSocial for making requests to remote resources.
`internal/id` - Code for generating IDs (ULIDs) for database models.
`internal/log` - Our logging implementation.
`internal/media` - Code related to managing + processing media attachments; images, video, emojis, etc.
`internal/messages` - Models for wrapping worker messages.
`internal/middleware` - Gin Gonic router middlewares: http signature checking, cache control, token checks, etc.
`internal/netutil` - HTTP / net request validation code.
`internal/oauth` - Wrapper code/interfaces for OAuth server implementation.
`internal/oidc` - Wrapper code/interfaces for OIDC claims and callbacks.
`internal/processing` - Logic for processing messages produced by the federation or client APIs. Much of the core business logic of GoToSocial is contained here.
`internal/regexes` - Regular expressions used for text parsing and matching of URLs, hashtags, mentions, etc.
`internal/router` - Wrapper for Gin HTTP router. Core HTTP logic is contained here. The router exposes functions for attaching routes, which are used by the code in `internal/api` handlers.
`internal/storage` - Wrapper for `codeberg.org/gruf/go-store` implementations. Local file storage and s3 logic goes here.
`internal/stream` - Websockets streaming logic.
`internal/text` - Text parsing and transformation. Status parsing logic is contained here -- both plain and markdown.
`internal/timeline` - Status timeline management code.
`internal/trans` - Code for exporting models to json backup files from the database, and importing backup json files into the database.
`internal/transport` - HTTP transport code and utilities.
`internal/typeutils` - Code for converting from internal database models to json, and back, or from ActivityPub format to internal database model format and vice versa. Basically, serdes.
`internal/uris` - Utilities for generating URIs used throughout GoToSocial.
`internal/util` - Odds and ends; small utility functions used by more than one package.
`internal/validate` - Model validation code -- currently not really used.
`internal/visibility` - Status visibility checking and filtering.
`internal/web` - Web UI handlers, specifically for serving web pages, the landing page, settings panels.
### Style / Linting / Formatting
It is a good idea to read the short official [Effective Go](https://golang.org/doc/effective_go) page before submitting code: this document is the foundation of many a style guide, for good reason, and GoToSocial more or less follows its advice.
Another useful style guide that we try to follow: [this one](https://github.com/bahlo/go-styleguide).
In addition, here are some specific highlights from Uber's Go style guide which agree with what we try to do in GtS:
- [Group Similar Declarations](https://github.com/uber-go/guide/blob/master/style.md#group-similar-declarations).
- [Reduce Nesting](https://github.com/uber-go/guide/blob/master/style.md#reduce-nesting).
- [Unnecessary Else](https://github.com/uber-go/guide/blob/master/style.md#unnecessary-else).
- [Local Variable Declarations](https://github.com/uber-go/guide/blob/master/style.md#local-variable-declarations).
- [Reduce Scope of Variables](https://github.com/uber-go/guide/blob/master/style.md#reduce-scope-of-variables).
- [Initializing Structs](https://github.com/uber-go/guide/blob/master/style.md#initializing-structs).
Before you submit any code, make sure to run `go fmt ./...` to update whitespace and other opinionated formatting.
We use [golangci-lint](https://golangci-lint.run/) for linting, which allows us to catch style inconsistencies and potential bugs or security issues, using static code analysis.
If you make a PR that doesn't pass the linter, it will be rejected. As such, it's good practice to run the linter locally before pushing or opening a PR.
To do this, first install the linter following the instructions [here](https://golangci-lint.run/usage/install/#local-installation).
Then, you can run the linter with:
```bash
golangci-lint run
```
If there's no output, great! It passed :)
### Testing
GoToSocial provides a [testrig](https://github.com/superseriousbusiness/gotosocial/tree/main/testrig) with a number of mock packages you can use in integration tests.
One thing that *isn't* mocked is the Database interface because it's just easier to use an in-memory SQLite database than to mock everything out.
#### Standalone Testrig with Semaphore
You can launch a testrig as a standalone server running at localhost, which you can connect to using something like [Semaphore](https://github.com/NickColley/semaphore/).
To do this, first build the gotosocial binary with `DEBUG=1 ./scripts/build.sh`.
Then, launch the testrig with the `DEBUG` environment variable set by invoking the binary as follows:
```bash
DEBUG=1 ./gotosocial testrig start
```
To run Semaphore locally in dev mode, first clone the [Semaphore](https://github.com/NickColley/semaphore/) repository, and then run the following commands in the cloned directory:
```bash
yarn # install dependencies
yarn run dev
```
The Semaphore instance will start running on `localhost:4002`.
To connect to the testrig, navigate to `http://localhost:4002` and enter your instance name as `localhost:8080`.
At the login screen, enter the email address `zork@example.org` and password `password`. You will get a confirmation prompt. Accept, and you are logged in as Zork.
Note the following constraints:
- Since the testrig uses an in-memory database, the database will be destroyed when the testrig is stopped.
- If you stop the testrig and start it again, any tokens or applications you created during your tests will also be removed. As such, you need to log out and in again every time you stop/start the rig.
- The testrig does not make any actual external HTTP calls, so federation will not work from a testrig.
#### Running automated tests
Tests can be run against both SQLite and Postgres.
##### SQLite
If you would like to run tests as quickly as possible, using an SQLite in-memory database, use:
```bash
go test ./...
```
##### Postgres
If you want to run tests against a Postgres database on localhost, run:
```bash
GTS_DB_TYPE="postgres" GTS_DB_ADDRESS="localhost" go test -p 1 ./...
```
In the above command, it is assumed you are using the default Postgres password of `postgres`.
We set `-p 1` when running against Postgres because it requires tests to run in serial, not in parallel.
#### CLI Tests
In [./test/envparsing.sh](./test/envparsing.sh) there's a test for making sure that CLI flags, config, and environment variables get parsed as expected.
Although this test *is* part of the CI/CD testing process, you probably won't need to worry too much about running it yourself. That is, unless you're messing about with code inside the `main` package in `cmd/gotosocial`, or inside the `config` package in `internal/config`.
#### Federation
By using the support for loading TLS files from disk it is possible to have two or more local instances with TLS to allow for (manually) testing federation.
You'll need to set the following configuration options:
- `GTS_TLS_CERTIFICATE_CHAIN`: poiting to a PEM-encoded certificate chain including the public certificate.
- `GTS_TLS_CERTIFICATE_KEY`: pointing to a PEM-encoded private key.
Additionally, for the Go HTTP client to recognise certificates issued by a custom CA as valid, you'll need to set one of:
- `SSL_CERT_FILE`: pointing to the public key of your custom CA.
- `SSL_CERT_DIR`: a `:`-separated list of directories to load CA certificates from.
The above `SSL_CERT` variables work on Unix-like systems only, excluding Mac. See https://pkg.go.dev/crypto/x509#SystemCertPool. If you are running your tests on an architecture that doesn't support setting the above variables, you can instead disable TLS certificate verification for the HTTP client entirely by setting `http-client.tls-insecure-skip-verify` to `true` in the config.yaml file.
You'll additionally need functioning DNS for your two instance names, which you can achieve through entries in `/etc/hosts` or by running a local DNS server like [dnsmasq](https://thekelleys.org.uk/dnsmasq/doc.html).
### Updating Swagger docs
GoToSocial uses [go-swagger](https://goswagger.io) to generate Swagger API documentation from code annotations.
You can install go-swagger following the instructions [here](https://goswagger.io/install.html).
If you change Swagger annotations on any of the API paths, you can generate a new Swagger file at `./docs/api/swagger.yaml` by running:
```bash
swagger generate spec --scan-models --exclude-deps -o docs/api/swagger.yaml
```
### CI/CD configuration
GoToSocial uses [Drone](https://www.drone.io/) for CI/CD tasks like running tests, linting, and building Docker containers.
These runs are integrated with GitHub, and will be run on opening a pull request or merging into main.
The Drone instance for GoToSocial is [here](https://drone.superseriousbusiness.org/superseriousbusiness/gotosocial).
The `drone.yml` file is [here](./.drone.yml) — this defines how and when Drone should run. Documentation for Drone is [here](https://docs.drone.io/).
It is worth noting that the `drone.yml` file must be signed by the Drone admin account to be considered valid. This must be done every time the file is changed. This is to prevent tampering and hijacking of the Drone instance. See [here](https://docs.drone.io/signature/).
To sign the file, first install and setup the [drone cli tool](https://docs.drone.io/cli/install/). Then, run:
```bash
drone -t PUT_YOUR_DRONE_ADMIN_TOKEN_HERE -s https://drone.superseriousbusiness.org sign superseriousbusiness/gotosocial --save
```
### Release Checklist
First things first: If this is a security hot-fix, we'll probably rush through this list, and make a prettier release a few days later.
Now, with that out of the way, here's our Checklist.
GoToSocial follows [Semantic Versioning](https://semver.org/).
So our first concern on the Checklist is:
- What version are we releasing?
Next we need to check:
- Do the assets have to be rebuilt and committed to the repository.
- Do the swagger docs have to be rebuilt?
On the project management side:
- Are there any issues that have to be moved to a different milestone?
- Are there any things on the [Roadmap](./ROADMAP.md) that can be ticked off?
Once we're happy with our Checklist, we can create the tag, and push it.
And the rest [is automation](./.drone.yml).
We can now head to GitHub, and add some personality to the release notes.
Finally, we make announcements on the all our channels that the release is out!
#### What if something goes wrong?
Sometimes things go awry.
We release a buggy release, we forgot something ­ something important.
If the release is so bad that it's unusable ­ or dangerous! ­ to a great part of our user-base, we can pull.
That is: Delete the tag.
Either way, once we've resolved the issue, we just start from the top of this list again. Version numbers are cheap. It's cheap to burn them.

View file

@ -2,7 +2,7 @@
# Dockerfile reference: https://docs.docker.com/engine/reference/builder/
# stage 1: generate up-to-date swagger.yaml to put in the final container
FROM --platform=${BUILDPLATFORM} quay.io/goswagger/swagger:v0.30.0 AS swagger
FROM --platform=${BUILDPLATFORM} quay.io/goswagger/swagger:v0.30.4 AS swagger
COPY go.mod /go/src/github.com/superseriousbusiness/gotosocial/go.mod
COPY go.sum /go/src/github.com/superseriousbusiness/gotosocial/go.sum
@ -12,7 +12,7 @@ WORKDIR /go/src/github.com/superseriousbusiness/gotosocial
RUN swagger generate spec -o /go/src/github.com/superseriousbusiness/gotosocial/swagger.yaml --scan-models
# stage 2: generate the web/assets/dist bundles
FROM --platform=${BUILDPLATFORM} node:16.15.1-alpine3.15 AS bundler
FROM --platform=${BUILDPLATFORM} node:16.19.1-alpine3.17 AS bundler
COPY web web
RUN yarn install --cwd web/source && \
@ -20,7 +20,7 @@ RUN yarn install --cwd web/source && \
rm -r web/source
# stage 3: build the executor container
FROM --platform=${TARGETPLATFORM} alpine:3.15.4 as executor
FROM --platform=${TARGETPLATFORM} alpine:3.17.2 as executor
# switch to non-root user:group for GtS
USER 1000:1000

163
README.md
View file

@ -8,9 +8,9 @@ With GoToSocial, you can keep in touch with your friends, post, read, and share
<img src="./docs/assets/sloth.png" width="300"/>
</p>
**GoToSocial is still [ALPHA SOFTWARE](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha)**. It is already deployable and useable, and it federates cleanly with many other Fediverse servers (not yet all). However, many things are not yet implemented, and there are plenty of bugs! We foresee entering beta somewhere in 2023.
**GoToSocial is still [ALPHA SOFTWARE](https://en.wikipedia.org/wiki/Software_release_life_cycle#Alpha)**. It is already deployable and useable, and it federates cleanly with many other Fediverse servers (not yet all). However, many things are not yet implemented, and there are plenty of bugs! We foresee entering beta around the beginning of 2024.
Documentation is at [docs.gotosocial.org](https://docs.gotosocial.org). You can skip straight to the API documentation [here](https://docs.gotosocial.org/en/latest/api/swagger/).
Documentation is at [docs.gotosocial.org](https://docs.gotosocial.org). You can skip straight to the API documentation [here](https://docs.gotosocial.org/en/latest/api/swagger/). To build from source, check the [CONTRIBUTING.md](./CONTRIBUTING.md) file.
Here's a screenshot of the instance landing page!
@ -33,20 +33,22 @@ Here's a screenshot of the instance landing page!
- [Wishlist](#wishlist)
- [Getting Started](#getting-started)
- [Third-Party Packaging](#third-party-packaging)
- [Distribution packaging](#distribution-packaging)
- [Self-hosting](#self-hosting)
- [Known Issues](#known-issues)
- [Client App Issues](#client-app-issues)
- [Federation Issues](#federation-issues)
- [Contributing](#contributing)
- [Building](#building)
- [Contact](#contact)
- [Credits](#credits)
- [Libraries](#libraries)
- [Image Attribution](#image-attribution)
- [Developers](#developers)
- [Image Attribution and Licensing](#image-attribution-and-licensing)
- [Team](#team)
- [Special Thanks](#special-thanks)
- [Sponsorship + Funding](#sponsorship--funding)
- [OpenCollective](#opencollective)
- [LiberaPay](#liberapay)
- [Provisos](#provisos)
- [Crowdfunding](#crowdfunding)
- [NLnet](#nlnet)
- [License](#license)
## What is GoToSocial?
@ -89,13 +91,13 @@ For a detailed view on what's implemented and what's not, and progress made towa
The Mastodon API has become the de facto standard for client communication with federated servers, so GoToSocial has implemented and extended the API with custom functionality.
In short, this means full support for modern, beautiful apps like [Tusky](https://tusky.app/) and [Pinafore](https://pinafore.social/).
In short, this means full support for modern, beautiful apps like [Tusky](https://tusky.app/) and [Semaphore](https://semaphore.social/).
Tusky | Pinafore
Tusky | Semaphore
:-----------------------------------------------------------:|:------------------------------------------------------------------:
![An image of GoToSocial in Tusky](./docs/assets/tusky.png) | ![An image of GoToSocial in Pinafore](./docs/assets/pinafore.png)
![An image of GoToSocial in Tusky](./docs/assets/tusky.png) | ![An image of GoToSocial in Semaphore](./docs/assets/semaphore.png)
If you're used to using Mastodon with Tusky or Pinafore, you'll find using GoToSocial a breeze.
If you're used to using Mastodon with Tusky or Semaphore, you'll find using GoToSocial a breeze.
### Granular post settings
@ -135,8 +137,8 @@ GoToSocial plays nice with lower-powered machines like Raspberry Pi, old laptops
GoToSocial doesn't apply a one-size-fits-all approach to federation. Who your server federates with should be up to you.
- 'Normal' federation; discover new servers.
- *Allow list*-only federation; choose which servers you talk to.
- Zero federation; keep your server private.
- *Allow list*-only federation; choose which servers you talk to (not yet implemented).
- Zero federation; keep your server private (not yet implemented).
### OIDC integration
@ -169,21 +171,30 @@ All docs for installation and configuration are hosted at [docs.gotosocial.org](
## Third-Party Packaging
Thank you so much to the cool people who have put time and energy into packaging GoToSocial! Known third-party packaging projects are listed below:
Thank you so much to the cool people who have put time and energy into packaging GoToSocial!
- [YunoHost GoToSocial Packaging](https://github.com/YunoHost-Apps/gotosocial_ynh) by [OniriCorpe](https://github.com/OniriCorpe).
- GoToSocial Helm Charts:
- [GoToSocial Helm Chart](https://github.com/Maxxblow/charts/tree/main/charts/gotosocial) by [0hlov3](https://github.com/0hlov3).
### Distribution packaging
These packages are not maintained by GoToSocial, so please direct questions and issues to the repository maintainers (and donate to them!).
[![Packaging status](https://repology.org/badge/vertical-allrepos/gotosocial.svg)](https://repology.org/project/gotosocial/versions)
### Self-hosting
You can deploy your own instance of GoToSocial with the help of:
- [YunoHost GoToSocial Packaging](https://github.com/YunoHost-Apps/gotosocial_ynh) by [OniriCorpe](https://github.com/OniriCorpe).
- [Ansible Playbook (MASH)](https://github.com/mother-of-all-self-hosting/mash-playbook): The playbook supports a many services, including GoToSocial. [Documentation](https://github.com/mother-of-all-self-hosting/mash-playbook/blob/main/docs/services/gotosocial.md)
- GoToSocial Helm Charts:
- [GoToSocial Helm Chart](https://github.com/fSocietySocial/charts/tree/main/charts/gotosocial) by [0hlov3](https://github.com/0hlov3).
## Known Issues
Since GoToSocial is still in alpha, there are plenty of bugs. We use [GitHub issues](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) to track these. The [FAQ](docs/faq.md) also describes some of the features that haven't been implemented yet.
### Client App Issues
GoToSocial works great with Tusky and Pinafore, but some other client applications still need work or have issues connecting to GoToSocial. We're tracking them [right here](https://github.com/superseriousbusiness/gotosocial/projects/5). It's our goal to make any app that's compatible with the Mastodon API work seamlessly with GoToSocial.
GoToSocial works great with Tusky and Semaphore, but some other client applications still need work or have issues connecting to GoToSocial. We're tracking them [right here](https://github.com/superseriousbusiness/gotosocial/projects/5). It's our goal to make any app that's compatible with the Mastodon API work seamlessly with GoToSocial.
### Federation Issues
@ -193,6 +204,10 @@ Since every ActivityPub server implementation has a slightly different interpret
You would like to contribute to GtS? Great! ❤️❤️❤️ Check out the issues page to see if there's anything you intend to jump in on, and read the [CONTRIBUTING.md](./CONTRIBUTING.md) file for guidelines and setting up your dev environment.
## Building
Instructions for building GoToSocial from source are in the [CONTRIBUTING.md](./CONTRIBUTING.md) file.
## Contact
For questions and comments, you can [join our Matrix space](https://matrix.to/#/#gotosocial-space:superseriousbusiness.org) at `#gotosocial-space:superseriousbusiness.org`. This is the quickest way to reach the devs. You can also mail [admin@gotosocial.org](mailto:admin@gotosocial.org).
@ -203,67 +218,93 @@ For bugs and feature requests, please check to see if there's [already an issue]
### Libraries
The following libraries and frameworks are used by GoToSocial, with gratitude 💕
The following open source libraries, frameworks, and tools are used by GoToSocial, with gratitude 💕
- [abema/go-mp4](https://github.com/abema/go-mp4); mp4 parsing. [MIT License](https://spdx.org/licenses/MIT.html).
- [buckket/go-blurhash](https://github.com/buckket/go-blurhash); used for generating image blurhashes. [GPL-3.0 License](https://spdx.org/licenses/GPL-3.0-only.html).
- [coreos/go-oidc](https://github.com/coreos/go-oidc); OIDC client library. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [disintegration/imaging](https://github.com/disintegration/imaging); image resizing. [MIT License](https://spdx.org/licenses/MIT.html).
- [gin-gonic/gin](https://github.com/gin-gonic/gin); speedy router engine. [MIT License](https://spdx.org/licenses/MIT.html).
- [DmitriyVTitov/size](https://github.com/DmitriyVTitov/size); runtime model memory size calculations. [MIT License](https://spdx.org/licenses/MIT.html).
- Gin:
- [gin-contrib/cors](https://github.com/gin-contrib/cors); Gin CORS middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [gin-contrib/gzip](https://github.com/gin-contrib/gzip); Gin gzip middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [gin-contrib/sessions](https://github.com/gin-contrib/sessions); Gin sessions middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [gin-contrib/static](https://github.com/gin-contrib/static); Gin static page middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [gin-gonic/gin](https://github.com/gin-gonic/gin); speedy router engine. [MIT License](https://spdx.org/licenses/MIT.html).
- [go-fed/httpsig](https://github.com/go-fed/httpsig); secure HTTP signature library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [google/uuid](https://github.com/google/uuid); UUID generation. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [google/wuffs](https://github.com/google/wuffs); png-stripping code. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [go-playground/validator](https://github.com/go-playground/validator); struct validation. [MIT License](https://spdx.org/licenses/MIT.html).
- [gorilla/feeds](https://github.com/gorilla/feeds); RSS + Atom feed generation. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
- [gorilla/websocket](https://github.com/gorilla/websocket); Websocket connectivity. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
- [gruf/go-debug](https://codeberg.org/gruf/go-debug); profiling support in debug builds. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-bytesize](https://codeberg.org/gruf/go-bytesize); byte size parsing / formatting. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-cache](https://codeberg.org/gruf/go-cache); object caching. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-kv](https://codeberg.org/gruf/go-kv); key-value field formatting. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-mutexes](https://codeberg.org/gruf/go-mutexes); mutex map. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-runners](https://codeberg.org/gruf/go-runners); worker pool library. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-store](https://codeberg.org/gruf/go-store); local media store. [MIT License](https://spdx.org/licenses/MIT.html).
- Go-Playground:
- [go-playground/form](https://github.com/go-playground/form); funky form mapping support. [MIT License](https://spdx.org/licenses/MIT.html).
- [go-playground/validator](https://github.com/go-playground/validator); struct validation. [MIT License](https://spdx.org/licenses/MIT.html).
- Gorilla:
- [gorilla/feeds](https://github.com/gorilla/feeds); RSS + Atom feed generation. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
- [gorilla/websocket](https://github.com/gorilla/websocket); Websocket connectivity. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
- [go-swagger/go-swagger](https://github.com/go-swagger/go-swagger); Swagger OpenAPI spec generation. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- gruf:
- [gruf/go-bytesize](https://codeberg.org/gruf/go-bytesize); byte size parsing / formatting. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-cache](https://codeberg.org/gruf/go-cache); object & result caching. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-debug](https://codeberg.org/gruf/go-debug); debug build tag. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-errors](https://codeberg.org/gruf/go-errors); performant multi-error checking [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-fastcopy](https://codeberg.org/gruf/go-fastcopy); performant pooled I/O copying [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-kv](https://codeberg.org/gruf/go-kv); log field formatting. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-mutexes](https://codeberg.org/gruf/go-mutexes); safemutex & mutex map. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-runners](https://codeberg.org/gruf/go-runners); workerpools and synchronization. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-sched](https://codeberg.org/gruf/go-sched); task scheduler. [MIT License](https://spdx.org/licenses/MIT.html).
- [gruf/go-store](https://codeberg.org/gruf/go-store); file storage backend (local & s3). [MIT License](https://spdx.org/licenses/MIT.html).
- [h2non/filetype](https://github.com/h2non/filetype); filetype checking. [MIT License](https://spdx.org/licenses/MIT.html).
- [jackc/pgx](https://github.com/jackc/pgx); Postgres driver. [MIT License](https://spdx.org/licenses/MIT.html).
- jackc:
- [jackc/pgx](https://github.com/jackc/pgconn); Postgres driver. [MIT License](https://spdx.org/licenses/MIT.html).
- [jackc/pgx](https://github.com/jackc/pgx); Postgres driver and toolkit. [MIT License](https://spdx.org/licenses/MIT.html).
- [KimMachineGun/automemlimit](https://github.com/KimMachineGun/automemlimit); cgroups memory limit checking. [MIT License](https://spdx.org/licenses/MIT.html).
- [mcuadros/go-syslog](https://github.com/mcuadros/go-syslog); Syslog server library. [MIT License](https://spdx.org/licenses/MIT.html).
- [microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday); HTML user-input sanitization. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [miekg/dns](https://github.com/miekg/dns); DNS utilities. [Go License](https://go.dev/LICENSE).
- [minio/minio-go](https://github.com/minio/minio-go); S3 client SDK. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [mitchellh/mapstructure](https://github.com/mitchellh/mapstructure); Go interface => struct parsing. [MIT License](https://spdx.org/licenses/MIT.html).
- [modernc.org/sqlite](https://gitlab.com/cznic/sqlite); cgo-free port of SQLite. [Other License](https://gitlab.com/cznic/sqlite/-/blob/master/LICENSE).
- [modernc.org/ccgo](https://gitlab.com/cznic/ccgo); c99 AST -> Go translater. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [modernc.org/libc](https://gitlab.com/cznic/libc); C-runtime services. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [mvdan/xurls](https://github.com/mvdan/xurls); URL parsing regular expressions. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [mvdan.cc/xurls](https://github.com/mvdan/xurls); URL parsing regular expressions. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [oklog/ulid](https://github.com/oklog/ulid); sequential, database-friendly ID generation. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [ReneKroon/ttlcache](https://github.com/ReneKroon/ttlcache); in-memory caching. [MIT License](https://spdx.org/licenses/MIT.html).
- [robfig/cron](https://github.com/robfig/cron); cron job scheduling. [MIT License](https://spdx.org/licenses/MIT.html).
- [russross/blackfriday](https://github.com/russross/blackfriday); markdown parsing for statuses. [Simplified BSD License](https://spdx.org/licenses/BSD-2-Clause.html).
- [spf13/cobra](https://github.com/spf13/cobra); command-line tooling. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [spf13/pflag](https://github.com/spf13/pflag); command-line flag utilities. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [spf13/viper](https://github.com/spf13/viper); configuration management. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [open-telemetry/opentelemetry-go](https://github.com/open-telemetry/opentelemetry-go); OpenTelemetry API + SDK. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- spf13:
- [spf13/cobra](https://github.com/spf13/cobra); command-line tooling. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [spf13/viper](https://github.com/spf13/viper); configuration management. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- [stretchr/testify](https://github.com/stretchr/testify); test framework. [MIT License](https://spdx.org/licenses/MIT.html).
- [superseriousbusiness/exif-terminator](https://github.com/superseriousbusiness/exif-terminator); EXIF data removal. [GNU AGPL v3 LICENSE](https://spdx.org/licenses/AGPL-3.0-or-later.html).
- [superseriousbusiness/activity](https://github.com/superseriousbusiness/activity) forked from [go-fed/activity](https://github.com/go-fed/activity); Golang ActivityPub/ActivityStreams library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [superseriousbusiness/oauth2](https://github.com/superseriousbusiness/oauth2) forked from [go-oauth2/oauth2](https://github.com/go-oauth2/oauth2); OAuth server framework and token handling. [MIT License](https://spdx.org/licenses/MIT.html).
- [go-swagger/go-swagger](https://github.com/go-swagger/go-swagger); Swagger OpenAPI spec generation. [Apache-2.0 License](https://spdx.org/licenses/Apache-2.0.html).
- superseriousbusiness:
- [superseriousbusiness/activity](https://github.com/superseriousbusiness/activity) forked from [go-fed/activity](https://github.com/go-fed/activity); Golang ActivityPub/ActivityStreams library. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html).
- [superseriousbusiness/exif-terminator](https://github.com/superseriousbusiness/exif-terminator); EXIF data removal. [GNU AGPL v3 LICENSE](https://spdx.org/licenses/AGPL-3.0-or-later.html).
- [superseriousbusiness/oauth2](https://github.com/superseriousbusiness/oauth2) forked from [go-oauth2/oauth2](https://github.com/go-oauth2/oauth2); OAuth server framework and token handling. [MIT License](https://spdx.org/licenses/MIT.html).
- [tdewolff/minify](https://github.com/tdewolff/minify); HTML minification for Markdown-submitted posts. [MIT License](https://spdx.org/licenses/MIT.html).
- [uber-go/automaxprocs](https://github.com/uber-go/automaxprocs); GOMAXPROCS automation. [MIT License](https://spdx.org/licenses/MIT.html).
- [ulule/limiter](https://github.com/ulule/limiter); http rate limit middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [uptrace/bun](https://github.com/uptrace/bun); database ORM. [BSD-2-Clause License](https://spdx.org/licenses/BSD-2-Clause.html).
- [wagslane/go-password-validator](https://github.com/wagslane/go-password-validator); password strength validation. [MIT License](https://spdx.org/licenses/MIT.html).
- [ulule/limiter](https://github.com/ulule/limiter); http rate limit middleware. [MIT License](https://spdx.org/licenses/MIT.html).
- [yuin/goldmark](https://github.com/yuin/goldmark); markdown parser. [MIT License](https://spdx.org/licenses/MIT.html).
### Image Attribution
### Image Attribution and Licensing
Sloth logo by [Anna Abramek](https://abramek.art/), Copyright (C) 2021-2022 the GoToSocial Authors.
Sloth logo by [Anna Abramek](https://abramek.art/).
### Developers
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />The GoToSocial sloth mascot is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
The Creative Commons Attribution-ShareAlike 4.0 International License license applies specifically to the following files and subdirectories of this repository:
- [sloth logo png](./web/assets/logo.png)
- [sloth logo svg](./web/assets/logo.svg)
- [all default avatars](./web/assets/default_avatars)
Under the terms of the license, you are free to:
- Share — copy and redistribute the abovementioned material in any medium or format.
- Adapt — remix, transform, and build upon the abovementioned material for any purpose, even commercially.
### Team
In alphabetical order (... and order of smell):
- f0x \[[donate with liberapay](https://liberapay.com/f0x)\]
- kim \[check out my code @ [codeberg](https://codeberg.org/gruf), or find me @ [@kim](https://k.iim.gay/@kim)\]
- tobi \[[donate with liberapay](https://liberapay.com/GoToSocial/)\]
- maloki \[[@maloki@goblin.technology](https://goblin.technology/@maloki)\]
### Special Thanks
@ -273,23 +314,27 @@ Thanks to everyone who has used GtS, opened an issue, suggested something, given
## Sponsorship + Funding
### OpenCollective
**Please note: GoToSocial has NO CORPORATE SPONSORS and does not desire corporate sponsorship. In addition, we do not take donations from any of the following: adult websites, affiliate and review websites, casinos and gambling, insurance and financial products (credit), pharmacy products, SEO services and social media buying, VPN and proxy services, and essay writing services. Donations from such sources will be automatically rejected.**
### Crowdfunding
![open collective Standard Sloth badge](https://opencollective.com/gotosocial/tiers/standard-sloth/badge.svg?label=Standard%20Sloth&color=brightgreen) ![open collective Stable Sloth badge](https://opencollective.com/gotosocial/tiers/stable-sloth/badge.svg?label=Stable%20Sloth&color=green) ![open collective Special Sloth badge](https://opencollective.com/gotosocial/tiers/special-sloth/badge.svg?label=Special%20Sloth&color=yellowgreen) ![open collective Sugar Sloth badge](https://opencollective.com/gotosocial/tiers/sugar-sloth/badge.svg?label=Sugar%20Sloth&color=blue)
Currently, work on GoToSocial is funded through donations to our [OpenCollective](https://opencollective.com/gotosocial) page.
If you would like to donate to GoToSocial to keep the lights on during development, [you can do so here](https://opencollective.com/gotosocial#support)! 💕 🦥 💕 Thank you!
### LiberaPay
If you would like to donate to GoToSocial to keep the lights on during development, [you can do so via our OpenCollective page](https://opencollective.com/gotosocial#support)!
![LiberaPay patrons](https://img.shields.io/liberapay/patrons/GoToSocial.svg?logo=liberapay) ![receives via LiberaPay](https://img.shields.io/liberapay/receives/GoToSocial.svg?logo=liberapay)
If you prefer, we also have an account on LiberaPay! You can find that [right here](https://liberapay.com/GoToSocial/).
### Provisos
Crowdfunded donations to our OpenCollective and Liberapay accounts go towards paying the core team, paying server costs, and paying for GtS art, design, and other bits and bobs.
**Please note: GoToSocial has NO CORPORATE SPONSORS and does not desire corporate sponsorship. In addition, we do not take donations from any of the following: adult websites, affiliate and review websites, casinos and gambling, insurance and financial products (credit), pharmacy products, SEO services and social media buying, VPN and proxy services, and essay writing services. Donations from such sources will be automatically rejected.**
💕 🦥 💕 Thank you!
### NLnet
<img src="https://nlnet.nl/logo/NGI/NGIZero-green.hex.svg" width="75" alt="NGIZero logo"/>
Combined with the above crowdfunding sources, 2023 Alpha development of GoToSocial is also funded by a 50,000 EUR grant from the [NGI0 Entrust Fund](https://nlnet.nl/entrust/), via [NLnet](https://nlnet.nl/). See [here](https://nlnet.nl/project/GoToSocial/#ack) for more details. The successful grant application is archived [here](https://github.com/superseriousbusiness/gotosocial/blob/main/archive/nlnet/2022-next-generation-internet-zero.md).
## License
@ -303,4 +348,6 @@ If you modify the GoToSocial source code, and run that modified code in a way th
> \[I\]f you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software.
Copyright (C) 2021-2022 the GoToSocial Authors.
Copyright (C) 2021-2023 GoToSocial Authors
(I'm adding this here to take the crown of having the 1000th commit ~ kim)

View file

@ -1,291 +1,69 @@
# Roadmap <!-- omit in toc -->
# Roadmap to Beta <!-- omit in toc -->
This document contains the roadmap for GoToSocial to be considered eligible for its first [beta release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta), and a summary of progress made towards that goal.
This document contains the roadmap for GoToSocial to be considered eligible for its first [beta release](https://en.wikipedia.org/wiki/Software_release_life_cycle#Beta).
All the dates contained in this document are best-guess only. It's useful to have a rough timeline, but things will undoubtedly change along the way.
All the info contained in this document is best-guess only. It's useful to have a rough timeline we can direct people to, but things will undoubtedly change along the way; don't hold us to anything in this doc!
Thank you to [NLnet](https://nlnet.nl) for helping to fund the alpha phase of GoToSocial development and get us moving towards beta!
Big thank you to all of our [Open Collective](https://opencollective.com/gotosocial) and [Liberapay](https://liberapay.com/gotosocial) contributors, who've helped us keep the lights on! 💕
## Table of Contents <!-- omit in toc -->
- [Beta Aims](#beta-aims)
- [Timeline](#timeline)
- [Q3 2022](#q3-2022)
- [Q4 2022](#q4-2022)
- [Q1 2023](#q1-2023)
- [Q2 2023](#q2-2023)
- [Q3 2023](#q3-2023)
- [Detailed To-do List](#detailed-to-do-list)
- [API Groups + Endpoints](#api-groups--endpoints)
- [Non-API tasks](#non-api-tasks)
- [Mid 2023](#mid-2023)
- [Mid/late 2023](#midlate-2023)
- [Late 2023](#late-2023)
- [Early 2024](#early-2024)
- [And then...](#and-then)
## Beta Aims
The milestone for beta in GoToSocial's case is to have a feature set that roughly compares to existing popular ActivityPub server implementations (minus features which we don't see as particularly important or useful). The beta milestone also includes GoToSocial-specific features which, we believe, are vital for user safety, such as local-only posting, block list subscriptions, and so on.
Every software project has a different idea of what it means to be "in beta". In our case, we want the beta version of GoToSocial to provide a feature set that roughly compares to existing popular ActivityPub server implementations.
Once feature parity is roughly in place, we will use beta time to start adding and polishing bonus features like slow federation, group moderation decisions, migration tooling, etc.
In other words, you should be able to use the beta version of GoToSocial as your go-to(!) fedi instance for following people and making posts, without running into too many issues with things being missing or not working properly.
We currently foresee entering beta phase around the middle of 2023, though this is only an estimate and is subject to change.
Our target for beta also includes features which, we believe, are vital for user safety and wellbeing, such as non-replyable posting, block list subscription, allow-list support, and so on.
Once we have the features we want in order to say "this is now a beta", we will use beta time to work on fixing bugs, tuning performance, and adding extra features which require a stable base to build on.
Our hope for beta is also that, once we're there, the client API will stay relatively stable, and folks can confidently start building applications on top of GoToSocial without worrying that the API will change overnight and necessitate major rewrites.
We currently foresee entering beta phase around the start of 2024, though this is only an estimate and is subject to change.
## Timeline
What follows is a per-quarter timeline of features that will be implemented on the road to beta. The timeline is calculated on the following assumptions:
What follows is a rough timeline of features that will be implemented on the road to beta. The timeline is calculated on the following assumptions:
- We will continue to develop at a pace that is similar to what we've done over the previous year.
- We will continue to develop at a pace that is similar to what we've done over the previous two years.
- Our combined bandwidth is roughly equivalent to one person working full time on the project.
- One distinct 'feature' takes one person 2-4 weeks to develop and test, depending on the size of the feature.
- There will be other bugs to fix in between implementing things, so we shouldn't pack in features too tightly.
Each quarter contains one 'big feature' which will probably take the longest amount of time that quarter.
**This timeline is a best-guess about when things will be implemented. The order of feature releases is not fixed. Things may go faster or slower depending on the number of hurdles we run into, and the amount of help we receive from community contributions of code. The timeline also does not include background tasks like admin, polishing existing features, refactoring code, release management, and ensuring compatibility with other AP implementations.**
**This timeline is a best-guess about when things will be implemented. The order of feature releases may change. It may go faster or slower depending on the number of hurdles we run into, and the amount of help we receive from community contributions of code. The timeline also does not include background tasks like admin, polishing existing features, refactoring code, and ensuring compatibility with other AP implementations.**
### Mid 2023
### Q3 2022
- **Hashtags** -- implement federating hashtags and viewing hashtags to allow users to discover posts that they might be interested in.
- **Block list subscriptions** -- allow instance admins to subscribe their instance to plaintext domain block lists (much of the work for this is already in place).
- **Direct conversation view** -- allow users to easily page through all direct-message conversations they're a part of.
- **Big Feature** -- User settings page: allow users to edit their profile page and settings through a web page served by the GtS instance, for cases where client apps don't implement their own settings page.
- Block list subscription support: allow instance admins to subscribe their instance to plaintext domain block lists (much of the work for this is already in place).
- Tag support: implement federating hashtags and viewing hashtags to allow users to discover posts that they might be interested in.
### Mid/late 2023
### Q4 2022
- **Polls** -- implementing parsing, creating, and voting in polls.
- **Mute posts/threads** -- opt-out of notifications for replies to a thread; no longer show a given post in your timeline.
- **Limited peering/allowlists** -- allow instance admins to limit federation with other instances by default.
- **Big Feature** — Video support: allow users to view + post videos (before we only implemented images and gifs).
- Custom emoji support: allow users to use custom emojis in posts. Fetch custom emojis from remote instances and display them properly.
- Pinned posts: allow users to 'feature' or 'pin' posts on their profile, and serve these featured posts via AP for other servers to see.
- Profile fields: allow users to set 'fields' on their profile: short key/value items that can display pronouns, links to websites, etc.
### Late 2023
### Q1 2023
- **Move activity** -- use the ActivityPub `Move` activity to support migration of a user's profile across servers.
- **Sign-up flow** -- allow users to submit a sign-up request to an instance; allow admins to moderate sign-up requests.
- **Big Feature** — Reports: allow users to file reports for abusive behavior etc. Expose the API for admins to view + act on reports. Handle federation of reports.
- List support: allow users to create lists of other users, which they can view as separate timelines.
- Polls support: allow users to create polls and vote in existing polls; federate the polls correctly via AP.
### Early 2024
### Q2 2023
- **Non-replyable posts** -- design a non-replyable post path for GoToSocial based on https://github.com/mastodon/mastodon/issues/14762#issuecomment-1196889788; allow users to create non-replyable posts.
- **Big Feature** — Sign-up flow. Allow users to submit a sign-up request to an instance. Allow admins to moderate sign-up requests.
- Direct conversations: Allow users to see all direct-message conversations they're a part of.
- Muting conversations: Allow users to mute notifications for conversations they're no longer interested in.
### And then...
### Q3 2023
- **Big Feature** — Support the `Move` Activity, to allow users to move across instances and Fediverse implementations.
- More to be confirmed.
## Detailed To-do List
### API Groups + Endpoints
Unfilled check - not yet implemented.
Filled check - implemented.
Crossed out - will not be implemented / will be stubbed only.
- [ ] Client-To-Server (Client REST API)
- [ ] Token and sign-in
- [x] /api/v1/apps POST (Create an application)
- [ ] /api/v1/apps/verify_credentials GET (Verify an application works)
- [x] /oauth/authorize GET (Show authorize page to user)
- [x] /oauth/authorize POST (Get an OAuth access code for an app/user)
- [x] /oauth/token POST (Obtain a user-level access token)
- [ ] /oauth/revoke POST (Revoke a user-level access token)
- [x] /auth/sign_in GET (Show form for user sign-in)
- [x] /auth/sign_in POST (Validate username and password and sign user in)
- [ ] Accounts
- [x] /api/v1/accounts POST (Register a new account)
- [x] /api/v1/accounts/verify_credentials GET (Verify account credentials with a user token)
- [x] /api/v1/accounts/update_credentials PATCH (Update user's display name/preferences)
- [x] /api/v1/accounts/:id GET (Get account information)
- [x] /api/v1/accounts/:id/statuses GET (Get an account's statuses)
- [x] /api/v1/accounts/:id/followers GET (Get an account's followers)
- [x] /api/v1/accounts/:id/following GET (Get an account's following)
- [ ] /api/v1/accounts/:id/featured_tags GET (Get an account's featured tags)
- [ ] /api/v1/accounts/:id/lists GET (Get lists containing this account)
- [x] /api/v1/accounts/:id/follow POST (Follow this account)
- [x] /api/v1/accounts/:id/unfollow POST (Unfollow this account)
- [x] /api/v1/accounts/:id/block POST (Block this account)
- [x] /api/v1/accounts/:id/unblock POST (Unblock this account)
- [ ] /api/v1/accounts/:id/mute POST (Mute this account)
- [ ] /api/v1/accounts/:id/unmute POST (Unmute this account)
- [ ] /api/v1/accounts/:id/pin POST (Feature this account on profile)
- [ ] /api/v1/accounts/:id/unpin POST (Remove this account from profile)
- [ ] /api/v1/accounts/:id/note POST (Make a personal note about this account)
- [x] /api/v1/accounts/relationships GET (Check relationships with accounts)
- [ ] /api/v1/accounts/search GET (Search for an account)
- ~~/api/v1/accounts/:id/identity_proofs GET (Get identity proofs for this account)~~
- [x] Favourites
- [x] /api/v1/favourites GET (See faved statuses)
- [ ] Mutes
- [ ] /api/v1/mutes GET (See list of muted accounts)
- [x] Blocks
- [x] /api/v1/blocks GET (See list of blocked accounts)
- [x] Domain Blocks
- [x] /api/v1/domain_blocks GET (See list of domain blocks)
- [x] /api/v1/domain_blocks POST (Create a domain block)
- [x] /api/v1/domain_blocks DELETE (Remove a domain block)
- [ ] Filters
- [ ] /api/v1/filters GET (Get list of filters)
- [ ] /api/v1/filters/:id GET (View a filter)
- [ ] /api/v1/filters POST (Create a filter)
- [ ] /api/v1/filters/:id PUT (Update a filter)
- [ ] /api/v1/filters/:id DELETE (Remove a filter)
- [ ] Reports
- [ ] /api/v1/reports POST (File a report)
- [x] Follow Requests
- [x] /api/v1/follow_requests GET (View pending follow requests)
- [x] /api/v1/follow_requests/:id/authorize POST (Accept a follow request)
- [x] /api/v1/follow_requests/:id/reject POST (Reject a follow request)
- [ ] Featured Tags
- [ ] /api/v1/featured_tags GET (View featured tags)
- [ ] /api/v1/featured_tags POST (Feature a tag)
- [ ] /api/v1/featured_tags/:id DELETE (Unfeature a tag)
- ~~/api/v1/featured_tags/suggestions GET (See most used tags)~~
- [ ] Preferences
- [ ] /api/v1/preferences GET (Get user preferences)
- [ ] Statuses
- [x] /api/v1/statuses POST (Create a new status)
- [x] /api/v1/statuses/:id GET (View an existing status)
- [x] /api/v1/statuses/:id DELETE (Delete a status)
- [x] /api/v1/statuses/:id/context GET (View statuses above and below status ID)
- [x] /api/v1/statuses/:id/reblogged_by GET (See who has reblogged a status)
- [x] /api/v1/statuses/:id/favourited_by GET (See who has faved a status)
- [x] /api/v1/statuses/:id/favourite POST (Fave a status)
- [x] /api/v1/statuses/:id/unfavourite POST (Unfave a status)
- [x] /api/v1/statuses/:id/reblog POST (Reblog a status)
- [x] /api/v1/statuses/:id/unreblog POST (Undo a reblog)
- [ ] /api/v1/statuses/:id/mute POST (Mute notifications on a status)
- [ ] /api/v1/statuses/:id/unmute POST (Unmute notifications on a status)
- [ ] /api/v1/statuses/:id/pin POST (Pin a status to profile)
- [ ] /api/v1/statuses/:id/unpin POST (Unpin a status from profile)
- ~~/api/v1/statuses/:id/bookmark POST (Bookmark a status)~~
- ~~/api/v1/statuses/:id/unbookmark POST (Undo a bookmark)~~
- [x] Media
- [x] /api/v1/media POST (Upload a media attachment)
- [x] /api/v1/media/:id GET (Get a media attachment)
- [x] /api/v1/media/:id PUT (Update an attachment)
- [ ] Polls
- [ ] /api/v1/polls/:id GET (Show a poll)
- [ ] /api/v1/polls/:id/votes POST (Vote on a poll)
- [ ] Timelines
- [x] /api/v1/timelines/public GET (See the public/federated timeline)
- [ ] /api/v1/timelines/tag/:hashtag GET (Get public statuses that use hashtag)
- [x] /api/v1/timelines/home GET (View statuses from followed users)
- [ ] /api/v1/timelines/list/:list_id GET (Get statuses in given list)
- [ ] Conversations
- [ ] /api/v1/conversations GET (Get a list of direct message convos)
- [ ] /api/v1/conversations/:id DELETE (Delete a direct message convo)
- [ ] /api/v1/conversations/:id POST (Mark a conversation as read)
- [ ] Lists
- [ ] /api/v1/lists GET (Show a list of lists)
- [ ] /api/v1/lists/:id GET (Show a single list)
- [ ] /api/v1/lists POST (Create a new list)
- [ ] /api/v1/lists/:id PUT (Update a list)
- [ ] /api/v1/lists/:id DELETE (Delete a list)
- [ ] /api/v1/lists/:id/accounts GET (View which accounts are in a list)
- [ ] /api/v1/lists/:id/accounts POST (Add accounts to a list)
- [ ] /api/v1/lists/:id/accounts DELETE (Remove accounts from a list)
- [ ] Markers
- [ ] /api/v1/markers GET (Get saved timeline position)
- [ ] /api/v1/markers POST (Save timeline position)
- [x] Streaming
- [x] /api/v1/streaming WEBSOCKETS (Stream live events to user via websockets)
- [ ] Notifications
- [x] /api/v1/notifications GET (Get list of notifications)
- [x] /api/v1/notifications/:id GET (Get a single notification)
- [ ] /api/v1/notifications/clear POST (Clear all notifications)
- [ ] /api/v1/notifications/:id POST (Clear a single notification)
- [x] Search
- [x] /api/v2/search GET (Get search query results)
- [ ] Instance
- [x] /api/v1/instance GET (Get instance information)
- [x] /api/v1/instance PATCH (Update instance information)
- [x] /api/v1/instance/peers GET (Get list of federated servers)
- ~~ /api/v1/instance/activity GET (Instance activity over the last 3 months, binned weekly.)~~
- [x] Custom Emojis
- [x] /api/v1/custom_emojis GET (Show this server's custom emoji)
- [ ] Admin
- [x] /api/v1/admin/custom_emojis POST (Upload a custom emoji for instance-wide usage)
- [ ] /api/v1/admin/accounts GET (View accounts filtered by criteria)
- [ ] /api/v1/admin/accounts/:id GET (View admin level info about an account)
- [x] /api/v1/admin/accounts/:id/action POST (Perform an admin action on account)
- [ ] /api/v1/admin/accounts/:id/approve POST (Approve pending account)
- [ ] /api/v1/admin/accounts/:id/reject POST (Deny pending account)
- [ ] /api/v1/admin/accounts/:id/enable POST (Re-enable a disabled account)
- [ ] /api/v1/admin/accounts/:id/unsilence POST (Unsilence a silenced account)
- [ ] /api/v1/admin/accounts/:id/unsuspend POST (Unsuspend a suspended account)
- [ ] /api/v1/admin/reports GET (View all reports)
- [ ] /api/v1/admin/reports/:id GET (View a single report)
- [ ] /api/v1/admin/reports/:id/assign_to_self POST (Assign a report to the current admin account)
- [ ] /api/v1/admin/reports/:id/unassign POST (Unassign a report)
- [ ] /api/v1/admin/reports/:id/resolve POST (Mark a report as resolved)
- [ ] /api/v1/admin/reports/:id/reopen POST (Reopen a closed report)
- [ ] Announcements
- [ ] /api/v1/announcements GET (Show all current announcements)
- [ ] /api/v1/announcements/:id/dismiss POST (Mark an announcement as read)
- [ ] /api/v1/announcements/:id/reactions/:name PUT (Add a reaction to an announcement)
- [ ] /api/v1/announcements/:id/reactions/:name DELETE (Remove a reaction from an announcement)
- [ ] Oembed
- [ ] /api/oembed GET (Get oembed metadata for a status URL)
- ~~Proofs~~
- ~~/api/proofs GET (View identity proofs)~~
- ~~Trends~~
- ~~/api/v1/trends GET (Get a list of trending tags for the last week)~~
- ~~Directory~~
- ~~/api/v1/directory GET (Show profiles this server is aware of.)~~
- ~~Endorsements~~
- ~~/api/v1/endorsements GET (View existing endorsements)~~
- ~~Push~~
- ~~/api/v1/push/subscription POST (Subscribe to push notifications)~~
- ~~/api/v1/push/subscription GET (Get current subscription)~~
- ~~/api/v1/push/subscription PUT (Change notification types)~~
- ~~/api/v1/push/subscription DELETE (Delete current subscription)~~
- ~~Scheduled Statuses~~
- ~~/api/v1/scheduled_statuses GET (View scheduled statuses)~~
- ~~/api/v1/scheduled_statuses/:id GET (View a scheduled status)~~
- ~~/api/v1/scheduled_statuses/:id PUT (Schedule a status)~~
- ~~/api/v1/scheduled_statuses/:id DELETE (Cancel a scheduled status)~~
- ~~Suggestions~~
- ~~/api/v1/suggestions GET (Get suggested accounts to follow)~~
- ~~/api/v1/suggestions/:account_id DELETE (Delete a suggestion)~~
- ~~Bookmarks~~
- ~~/api/v1/bookmarks GET (See bookmarked statuses)~~
### Non-API tasks
- [ ] Server-To-Server (Federation protocol)
- [x] Mechanism to trigger side effects from client AP
- [x] Webfinger account lookups
- [ ] Federation modes
- [ ] 'Slow' federation
- [ ] Reputation scoring system for instances
- [x] 'Greedy' federation
- [ ] No federation (insulate this instance from the Fediverse)
- [ ] Allow list
- [x] Secure HTTP signatures (creation and validation)
- [x] Storage
- [x] Internal/statuses/preferences etc
- [x] Postgres interface
- [x] SQLite interface
- [x] Media storage
- [x] Local storage interface
- [x] S3 storage interface
- [x] Cache
- [x] In-memory cache
- [ ] Security features
- [x] Authorization middleware
- [ ] Rate limiting middleware
- [ ] Scope middleware
- [x] Permissions/ACL middleware for admins+moderators
- [ ] Documentation
- [x] Swagger API documentation
- [x] ReadTheDocs.io documentation
- [x] Deployment documentation
- [ ] App creation guide
- [ ] Tooling
- [ ] Database migration tool
- [x] Admin CLI tool
- [x] Build
- [x] Docker containerization
- [x] Dockerfile
- [x] docker-compose.yml
- [ ] Tests
- [ ] Unit/integration
- [x] 25% coverage
- [ ] 50% coverage
- [ ] 90%+ coverage
- [ ] Benchmarking
BETA TIME baby!

109
archive/design/reports.md Normal file
View file

@ -0,0 +1,109 @@
# Reports / Flag Activity Federation
This document contains design notes for GoToSocial's federated (s2s) Flag functionality.
## What do existing implementations do?
Information below is true as of Jan 2023. If you're reading this much later, the below things may no longer apply.
### Mastodon
Mastodon uses the Flag activity to federate reports to other AP servers.
The Activity is wrapped inside a Create, which is addressed To the Inbox of the offending account.
To preserve anonymity of the reporter, the instance Actor is used as the Actor of the Activity.
Examples of the unwrapped Flag:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/actor",
"content": "misinfo: it's not a good morning",
"id": "https://example.org/341e866f-93f8-4755-9cf4-f8fb17f434fd",
"object": [
"https://bad.instance/users/tobi",
"https://bad.instance/users/tobi/statuses/01GP388K19DGXSV3SW2RXWM533"
],
"type": "Flag"
}
```
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/actor",
"content": "smellyyyyyyyyyyyyy",
"id": "https://example.org/3088184f-81b2-4545-8ce2-4cee4895449f",
"object": "https://bad.instance/users/tobi",
"type": "Flag"
}
```
The `content` field contains the report description.
The `object` field contains the reported Account URI and optionally one or more Note/Article/etc URIs. `object` value will be a string if just the Account URI is reported, or an array if the Account and one or more posts are being reported.
The `id` field is a generic URI that doesn't reveal any metadata. Trying to GET this URI gives a 404 Not Found error, which is OK since all the info needed to process the report is included in the Activity already.
### Misskey
Misskey uses the Flag activity to federate reports to other AP servers.
The Activity is wrapped inside a Create, which is addressed To the Inbox of the offending account.
To preserve anonymity of the reporter, the instance Actor is used as the Actor of the Activity.
Example of the unwrapped Flag:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/909i45meeo",
"content": "Note: https://bad.instance/@tobi/statuses/01GPB56GPJ37JTK9HW308HQKBQ\n-----\nincites anti-police behaviour while being cute! ⛔",
"id": "https://example.org/db22128d-884e-4358-9935-6a7c3940535d",
"object": "https://bad.instance/users/tobi",
"type": "Flag"
}
```
The `content` field contains the report description. Unlike with Mastodon, `content` also seems to include one or more statuses, as opposed to including statuses in the `object` field.
The `object` field contains the reported Account URI.
Trying to dereference the `id` field for a Misskey report with `Accept: application/activity+json` gives a 200 OK, but the returned content is some HTML unrelated to the report, so functionally equivalent to Mastodon's 404 behavior. Again, this is not really a problem.
### Calckey
Same as Misskey. Example:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "https://example.org/users/97wsu4gkns",
"content": "Note: https://bad.instance/@tobi/statuses/01GPB56GPJ37JTK9HW308HQKBQ\n-----\nTest report from Calckey",
"id": "https://example.org/b9a02404-d007-4b31-8dd6-bfc53387ad85",
"object": "https://bad.instance/users/tobi",
"type": "Flag"
}
```
### Pleroma / Akkoma
todo
### Friendica
Unsure: Friendica and GoToSocial still don't federate properly with one another (https://github.com/superseriousbusiness/gotosocial/issues/169) so it's hard to test this.
## What should GoToSocial do?
Since the above implementations of Flag seem fairly consistent, GoToSocial should do more or less the same thing when federating reports outwards. So GtS ought to adopt the Mastodon behavior:
- Wrap Flag Activity in a Create and deliver it to the offending account.
- Use the GtS instance Actor as the Actor of the Flag.
- Generate an ID that doesn't reveal who created the report.
- Include Actor and one or more Note / Article / etc URIs in the `object` field
For incoming reports, all the above fields should be handled in order to generate a report for admins to look at.

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package action

View file

@ -1,273 +1,333 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package account
import (
"context"
"errors"
"fmt"
"os"
"text/tabwriter"
"time"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/validate"
"golang.org/x/crypto/bcrypt"
)
// Create creates a new account in the database using the provided flags.
var Create action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
func initState(ctx context.Context) (*state.State, error) {
var state state.State
state.Caches.Init()
state.Caches.Start()
state.Workers.Start()
// Set the state DB connection
dbConn, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return nil, fmt.Errorf("error creating dbConn: %w", err)
}
state.DB = dbConn
return &state, nil
}
func stopState(ctx context.Context, state *state.State) error {
if err := state.DB.Stop(ctx); err != nil {
return fmt.Errorf("error stopping dbConn: %w", err)
}
state.Workers.Stop()
state.Caches.Stop()
return nil
}
// Create creates a new account and user
// in the database using the provided flags.
var Create action.GTSAction = func(ctx context.Context) error {
state, err := initState(ctx)
if err != nil {
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
usernameAvailable, err := dbConn.IsUsernameAvailable(ctx, username)
usernameAvailable, err := state.DB.IsUsernameAvailable(ctx, username)
if err != nil {
return err
}
if !usernameAvailable {
return fmt.Errorf("username %s is already in use", username)
}
email := config.GetAdminAccountEmail()
if email == "" {
return errors.New("no email set")
}
if err := validate.Email(email); err != nil {
return err
}
emailAvailable, err := dbConn.IsEmailAvailable(ctx, email)
emailAvailable, err := state.DB.IsEmailAvailable(ctx, email)
if err != nil {
return err
}
if !emailAvailable {
return fmt.Errorf("email address %s is already in use", email)
}
password := config.GetAdminAccountPassword()
if password == "" {
return errors.New("no password set")
}
if err := validate.NewPassword(password); err != nil {
if err := validate.Password(password); err != nil {
return err
}
_, err = dbConn.NewSignup(ctx, username, "", false, email, password, nil, "", "", true, false)
if _, err := state.DB.NewSignup(ctx, gtsmodel.NewSignup{
Username: username,
Email: email,
Password: password,
EmailVerified: true, // Assume cli user wants email marked as verified already.
PreApproved: true, // Assume cli user wants account marked as approved already.
}); err != nil {
return err
}
return stopState(ctx, state)
}
// List returns all existing local accounts.
var List action.GTSAction = func(ctx context.Context) error {
state, err := initState(ctx)
if err != nil {
return err
}
return dbConn.Stop(ctx)
users, err := state.DB.GetAllUsers(ctx)
if err != nil {
return err
}
fmtBool := func(b *bool) string {
if b == nil {
return "unknown"
}
if *b {
return "yes"
}
return "no"
}
fmtDate := func(t time.Time) string {
if t.Equal(time.Time{}) {
return "no"
}
return "yes"
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0)
fmt.Fprintln(w, "user\taccount\tapproved\tadmin\tmoderator\tsuspended\tconfirmed")
for _, u := range users {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", u.Account.Username, u.AccountID, fmtBool(u.Approved), fmtBool(u.Admin), fmtBool(u.Moderator), fmtDate(u.Account.SuspendedAt), fmtDate(u.ConfirmedAt))
}
w.Flush()
return nil
}
// Confirm sets a user to Approved, sets Email to the current UnconfirmedEmail value, and sets ConfirmedAt to now.
// Confirm sets a user to Approved, sets Email to the current
// UnconfirmedEmail value, and sets ConfirmedAt to now.
var Confirm action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
state, err := initState(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
a, err := dbConn.GetAccountByUsernameDomain(ctx, username, "")
account, err := state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
return err
}
u, err := dbConn.GetUserByAccountID(ctx, a.ID)
user, err := state.DB.GetUserByAccountID(ctx, account.ID)
if err != nil {
return err
}
updatingColumns := []string{"approved", "email", "confirmed_at", "updated_at"}
approved := true
u.Approved = &approved
u.Email = u.UnconfirmedEmail
u.ConfirmedAt = time.Now()
u.UpdatedAt = time.Now()
if err := dbConn.UpdateByID(ctx, u, u.ID, updatingColumns...); err != nil {
user.Approved = func() *bool { a := true; return &a }()
user.Email = user.UnconfirmedEmail
user.ConfirmedAt = time.Now()
if err := state.DB.UpdateUser(
ctx, user,
"approved", "email", "confirmed_at",
); err != nil {
return err
}
return dbConn.Stop(ctx)
return stopState(ctx, state)
}
// Promote sets a user to admin.
// Promote sets admin + moderator flags on a user to true.
var Promote action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
state, err := initState(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
a, err := dbConn.GetAccountByUsernameDomain(ctx, username, "")
account, err := state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
return err
}
u, err := dbConn.GetUserByAccountID(ctx, a.ID)
user, err := state.DB.GetUserByAccountID(ctx, account.ID)
if err != nil {
return err
}
admin := true
u.Admin = &admin
if err := dbConn.UpdateUser(ctx, u, "admin"); err != nil {
user.Admin = func() *bool { a := true; return &a }()
user.Moderator = func() *bool { a := true; return &a }()
if err := state.DB.UpdateUser(
ctx, user,
"admin", "moderator",
); err != nil {
return err
}
return dbConn.Stop(ctx)
return stopState(ctx, state)
}
// Demote sets admin on a user to false.
// Demote sets admin + moderator flags on a user to false.
var Demote action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
state, err := initState(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
a, err := dbConn.GetAccountByUsernameDomain(ctx, username, "")
a, err := state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
return err
}
u, err := dbConn.GetUserByAccountID(ctx, a.ID)
user, err := state.DB.GetUserByAccountID(ctx, a.ID)
if err != nil {
return err
}
admin := false
u.Admin = &admin
if err := dbConn.UpdateUser(ctx, u, "admin"); err != nil {
user.Admin = func() *bool { a := false; return &a }()
user.Moderator = func() *bool { a := false; return &a }()
if err := state.DB.UpdateUser(
ctx, user,
"admin", "moderator",
); err != nil {
return err
}
return dbConn.Stop(ctx)
return stopState(ctx, state)
}
// Disable sets Disabled to true on a user.
var Disable action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
state, err := initState(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
a, err := dbConn.GetAccountByUsernameDomain(ctx, username, "")
account, err := state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
return err
}
u, err := dbConn.GetUserByAccountID(ctx, a.ID)
user, err := state.DB.GetUserByAccountID(ctx, account.ID)
if err != nil {
return err
}
disabled := true
u.Disabled = &disabled
if err := dbConn.UpdateUser(ctx, u, "disabled"); err != nil {
user.Disabled = func() *bool { d := true; return &d }()
if err := state.DB.UpdateUser(
ctx, user,
"disabled",
); err != nil {
return err
}
return dbConn.Stop(ctx)
return stopState(ctx, state)
}
// Password sets the password of target account.
var Password action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
state, err := initState(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
username := config.GetAdminAccountUsername()
if username == "" {
return errors.New("no username set")
}
if err := validate.Username(username); err != nil {
return err
}
password := config.GetAdminAccountPassword()
if password == "" {
return errors.New("no password set")
}
if err := validate.NewPassword(password); err != nil {
if err := validate.Password(password); err != nil {
return err
}
a, err := dbConn.GetAccountByUsernameDomain(ctx, username, "")
account, err := state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
return err
}
u, err := dbConn.GetUserByAccountID(ctx, a.ID)
user, err := state.DB.GetUserByAccountID(ctx, account.ID)
if err != nil {
return err
}
pw, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
encryptedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("error hashing password: %s", err)
}
u.EncryptedPassword = string(pw)
if err := dbConn.UpdateUser(ctx, u, "encrypted_password"); err != nil {
user.EncryptedPassword = string(encryptedPassword)
if err := state.DB.UpdateUser(
ctx, user,
"encrypted_password",
); err != nil {
return err
}
return nil
return stopState(ctx, state)
}

View file

@ -0,0 +1,165 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package media
import (
"bufio"
"context"
"fmt"
"os"
"path"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/state"
)
type list struct {
dbService db.DB
state *state.State
maxID string
limit int
out *bufio.Writer
}
func (l *list) GetAllMediaPaths(ctx context.Context, filter func(*gtsmodel.MediaAttachment) string) ([]string, error) {
res := make([]string, 0, 100)
for {
attachments, err := l.dbService.GetAttachments(ctx, l.maxID, l.limit)
if err != nil {
return nil, fmt.Errorf("failed to retrieve media metadata from database: %w", err)
}
for _, a := range attachments {
v := filter(a)
if v != "" {
res = append(res, v)
}
}
// If we got less results than our limit, we've reached the
// last page to retrieve and we can break the loop. If the
// last batch happens to contain exactly the same amount of
// items as the limit we'll end up doing one extra query.
if len(attachments) < l.limit {
break
}
// Grab the last ID from the batch and set it as the maxID
// that'll be used in the next iteration so we don't get items
// we've already seen.
l.maxID = attachments[len(attachments)-1].ID
}
return res, nil
}
func setupList(ctx context.Context) (*list, error) {
var state state.State
state.Caches.Init()
state.Caches.Start()
state.Workers.Start()
dbService, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return nil, fmt.Errorf("error creating dbservice: %w", err)
}
state.DB = dbService
return &list{
dbService: dbService,
state: &state,
limit: 200,
maxID: "",
out: bufio.NewWriter(os.Stdout),
}, nil
}
func (l *list) shutdown(ctx context.Context) error {
l.out.Flush()
err := l.dbService.Stop(ctx)
l.state.Workers.Stop()
l.state.Caches.Stop()
return err
}
var ListLocal action.GTSAction = func(ctx context.Context) error {
list, err := setupList(ctx)
if err != nil {
return err
}
defer func() {
// Ensure lister gets shutdown on exit.
if err := list.shutdown(ctx); err != nil {
log.Error(ctx, err)
}
}()
mediaPath := config.GetStorageLocalBasePath()
media, err := list.GetAllMediaPaths(
ctx,
func(m *gtsmodel.MediaAttachment) string {
if m.RemoteURL == "" {
return path.Join(mediaPath, m.File.Path)
}
return ""
})
if err != nil {
return err
}
for _, m := range media {
_, _ = list.out.WriteString(m + "\n")
}
return nil
}
var ListRemote action.GTSAction = func(ctx context.Context) error {
list, err := setupList(ctx)
if err != nil {
return err
}
defer func() {
// Ensure lister gets shutdown on exit.
if err := list.shutdown(ctx); err != nil {
log.Error(ctx, err)
}
}()
media, err := list.GetAllMediaPaths(
ctx,
func(m *gtsmodel.MediaAttachment) string {
return m.RemoteURL
})
if err != nil {
return err
}
for _, m := range media {
_, _ = list.out.WriteString(m + "\n")
}
return nil
}

View file

@ -0,0 +1,61 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package prune
import (
"context"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/log"
)
// All performs all media clean actions
var All action.GTSAction = func(ctx context.Context) error {
// Setup pruning utilities.
prune, err := setupPrune(ctx)
if err != nil {
return err
}
defer func() {
// Ensure pruner gets shutdown on exit.
if err := prune.shutdown(ctx); err != nil {
log.Error(ctx, err)
}
}()
if config.GetAdminMediaPruneDryRun() {
log.Info(ctx, "prune DRY RUN")
ctx = gtscontext.SetDryRun(ctx)
}
days := config.GetMediaRemoteCacheDays()
// Perform the actual pruning with logging.
prune.cleaner.Media().All(ctx, days)
prune.cleaner.Emoji().All(ctx, days)
// Perform a cleanup of storage (for removed local dirs).
if err := prune.storage.Storage.Clean(ctx); err != nil {
log.Error(ctx, "error cleaning storage: %v", err)
}
return nil
}

View file

@ -0,0 +1,92 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package prune
import (
"context"
"fmt"
"github.com/superseriousbusiness/gotosocial/internal/cleaner"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/media"
"github.com/superseriousbusiness/gotosocial/internal/state"
gtsstorage "github.com/superseriousbusiness/gotosocial/internal/storage"
)
type prune struct {
dbService db.DB
storage *gtsstorage.Driver
manager *media.Manager
cleaner *cleaner.Cleaner
state *state.State
}
func setupPrune(ctx context.Context) (*prune, error) {
var state state.State
state.Caches.Init()
state.Caches.Start()
state.Workers.Start()
dbService, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return nil, fmt.Errorf("error creating dbservice: %w", err)
}
state.DB = dbService
//nolint:contextcheck
storage, err := gtsstorage.AutoConfig()
if err != nil {
return nil, fmt.Errorf("error creating storage backend: %w", err)
}
state.Storage = storage
//nolint:contextcheck
manager := media.NewManager(&state)
//nolint:contextcheck
cleaner := cleaner.New(&state)
return &prune{
dbService: dbService,
storage: storage,
manager: manager,
cleaner: cleaner,
state: &state,
}, nil
}
func (p *prune) shutdown(ctx context.Context) error {
errs := gtserror.NewMultiError(2)
if err := p.storage.Close(); err != nil {
errs.Appendf("error closing storage backend: %w", err)
}
if err := p.dbService.Stop(ctx); err != nil {
errs.Appendf("error stopping database: %w", err)
}
p.state.Workers.Stop()
p.state.Caches.Stop()
return errs.Combine()
}

View file

@ -1,71 +1,57 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package prune
import (
"context"
"fmt"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/media"
gtsstorage "github.com/superseriousbusiness/gotosocial/internal/storage"
)
// Orphaned prunes orphaned media from storage.
var Orphaned action.GTSAction = func(ctx context.Context) error {
dbService, err := bundb.NewBunDBService(ctx)
// Setup pruning utilities.
prune, err := setupPrune(ctx)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
return err
}
storage, err := gtsstorage.AutoConfig()
if err != nil {
return fmt.Errorf("error creating storage backend: %w", err)
defer func() {
// Ensure pruner gets shutdown on exit.
if err := prune.shutdown(ctx); err != nil {
log.Error(ctx, err)
}
}()
if config.GetAdminMediaPruneDryRun() {
log.Info(ctx, "prune DRY RUN")
ctx = gtscontext.SetDryRun(ctx)
}
manager, err := media.NewManager(dbService, storage)
if err != nil {
return fmt.Errorf("error instantiating mediamanager: %s", err)
}
// Perform the actual pruning with logging.
prune.cleaner.Media().LogPruneOrphaned(ctx)
dry := config.GetAdminMediaPruneDryRun()
pruned, err := manager.PruneOrphaned(ctx, dry)
if err != nil {
return fmt.Errorf("error pruning: %s", err)
}
if dry {
log.Infof("DRY RUN: %d stored items are orphaned and eligible to be pruned", pruned)
} else {
log.Infof("%d stored items were orphaned and pruned", pruned)
}
if err := storage.Close(); err != nil {
return fmt.Errorf("error closing storage backend: %w", err)
}
if err := dbService.Stop(ctx); err != nil {
return fmt.Errorf("error closing dbservice: %s", err)
// Perform a cleanup of storage (for removed local dirs).
if err := prune.storage.Storage.Clean(ctx); err != nil {
log.Error(ctx, "error cleaning storage: %v", err)
}
return nil

View file

@ -0,0 +1,62 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package prune
import (
"context"
"time"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtscontext"
"github.com/superseriousbusiness/gotosocial/internal/log"
)
// Remote prunes old and/or unused remote media.
var Remote action.GTSAction = func(ctx context.Context) error {
// Setup pruning utilities.
prune, err := setupPrune(ctx)
if err != nil {
return err
}
defer func() {
// Ensure pruner gets shutdown on exit.
if err := prune.shutdown(ctx); err != nil {
log.Error(ctx, err)
}
}()
if config.GetAdminMediaPruneDryRun() {
log.Info(ctx, "prune DRY RUN")
ctx = gtscontext.SetDryRun(ctx)
}
t := time.Now().Add(-24 * time.Hour * time.Duration(config.GetMediaRemoteCacheDays()))
// Perform the actual pruning with logging.
prune.cleaner.Media().LogPruneUnused(ctx)
prune.cleaner.Media().LogUncacheRemote(ctx, t)
// Perform a cleanup of storage (for removed local dirs).
if err := prune.storage.Storage.Clean(ctx); err != nil {
log.Error(ctx, "error cleaning storage: %v", err)
}
return nil
}

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package trans
@ -26,16 +25,22 @@ import (
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/trans"
)
// Export exports info from the database into a file
var Export action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
var state state.State
dbConn, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
}
// Set the state DB connection
state.DB = dbConn
exporter := trans.NewExporter(dbConn)
path := config.GetAdminTransPath()

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package trans
@ -26,16 +25,22 @@ import (
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/trans"
)
// Import imports info from a file into the database
var Import action.GTSAction = func(ctx context.Context) error {
dbConn, err := bundb.NewBunDBService(ctx)
var state state.State
dbConn, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
}
// Set the state DB connection
state.DB = dbConn
importer := trans.NewImporter(dbConn)
path := config.GetAdminTransPath()

View file

@ -1,27 +1,26 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package config
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/config"
@ -39,13 +38,8 @@ var Config action.GTSAction = func(ctx context.Context) (err error) {
return err
}
// Marshal map to JSON
b, err := json.Marshal(raw)
if err != nil {
return err
}
// Print to stdout
fmt.Printf("%s\n", b)
return nil
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
err = enc.Encode(raw)
return err
}

View file

@ -1,56 +1,45 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package server
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"codeberg.org/gruf/go-sched"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/api"
"github.com/superseriousbusiness/gotosocial/internal/api/client/account"
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
"github.com/superseriousbusiness/gotosocial/internal/api/client/app"
"github.com/superseriousbusiness/gotosocial/internal/api/client/auth"
"github.com/superseriousbusiness/gotosocial/internal/api/client/blocks"
"github.com/superseriousbusiness/gotosocial/internal/api/client/emoji"
"github.com/superseriousbusiness/gotosocial/internal/api/client/favourites"
"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver"
"github.com/superseriousbusiness/gotosocial/internal/api/client/filter"
"github.com/superseriousbusiness/gotosocial/internal/api/client/followrequest"
"github.com/superseriousbusiness/gotosocial/internal/api/client/instance"
"github.com/superseriousbusiness/gotosocial/internal/api/client/list"
mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media"
"github.com/superseriousbusiness/gotosocial/internal/api/client/notification"
"github.com/superseriousbusiness/gotosocial/internal/api/client/search"
"github.com/superseriousbusiness/gotosocial/internal/api/client/status"
"github.com/superseriousbusiness/gotosocial/internal/api/client/streaming"
"github.com/superseriousbusiness/gotosocial/internal/api/client/timeline"
userClient "github.com/superseriousbusiness/gotosocial/internal/api/client/user"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/nodeinfo"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/user"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/webfinger"
"github.com/superseriousbusiness/gotosocial/internal/api/security"
"github.com/superseriousbusiness/gotosocial/internal/concurrency"
apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/middleware"
tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline"
"github.com/superseriousbusiness/gotosocial/internal/timeline"
"github.com/superseriousbusiness/gotosocial/internal/tracing"
"github.com/superseriousbusiness/gotosocial/internal/visibility"
"go.uber.org/automaxprocs/maxprocs"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/email"
@ -60,24 +49,47 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/httpclient"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/media"
"github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/oauth"
"github.com/superseriousbusiness/gotosocial/internal/oidc"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/router"
"github.com/superseriousbusiness/gotosocial/internal/state"
gtsstorage "github.com/superseriousbusiness/gotosocial/internal/storage"
"github.com/superseriousbusiness/gotosocial/internal/transport"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
"github.com/superseriousbusiness/gotosocial/internal/web"
// Inherit memory limit if set from cgroup
_ "github.com/KimMachineGun/automemlimit"
)
// Start creates and starts a gotosocial server
var Start action.GTSAction = func(ctx context.Context) error {
dbService, err := bundb.NewBunDBService(ctx)
if _, err := maxprocs.Set(maxprocs.Logger(nil)); err != nil {
log.Infof(ctx, "could not set CPU limits from cgroup: %s", err)
}
var state state.State
// Initialize caches
state.Caches.Init()
state.Caches.Start()
defer state.Caches.Stop()
// Initialize Tracing
if err := tracing.Initialize(); err != nil {
return fmt.Errorf("error initializing tracing: %w", err)
}
// Open connection to the database
dbService, err := bundb.NewBunDBService(ctx, &state)
if err != nil {
return fmt.Errorf("error creating dbservice: %s", err)
}
// Set the state DB connection
state.DB = dbService
if err := dbService.CreateInstanceAccount(ctx); err != nil {
return fmt.Errorf("error creating instance account: %s", err)
}
@ -86,134 +98,177 @@ var Start action.GTSAction = func(ctx context.Context) error {
return fmt.Errorf("error creating instance instance: %s", err)
}
// Create the client API and federator worker pools
// NOTE: these MUST NOT be used until they are passed to the
// processor and it is started. The reason being that the processor
// sets the Worker process functions and start the underlying pools
clientWorker := concurrency.NewWorkerPool[messages.FromClientAPI](-1, -1)
fedWorker := concurrency.NewWorkerPool[messages.FromFederator](-1, -1)
federatingDB := federatingdb.New(dbService, fedWorker)
router, err := router.New(ctx, dbService)
if err != nil {
return fmt.Errorf("error creating router: %s", err)
}
// build converters and util
typeConverter := typeutils.NewConverter(dbService)
// Open the storage backend
storage, err := gtsstorage.AutoConfig()
if err != nil {
return fmt.Errorf("error creating storage backend: %w", err)
}
// Build HTTP client (TODO: add configurables here)
client := httpclient.New(httpclient.Config{})
// Set the state storage driver
state.Storage = storage
// build backend handlers
mediaManager, err := media.NewManager(dbService, storage)
if err != nil {
return fmt.Errorf("error creating media manager: %s", err)
}
// Build HTTP client
client := httpclient.New(httpclient.Config{
AllowRanges: config.MustParseIPPrefixes(config.GetHTTPClientAllowIPs()),
BlockRanges: config.MustParseIPPrefixes(config.GetHTTPClientBlockIPs()),
Timeout: config.GetHTTPClientTimeout(),
TLSInsecureSkipVerify: config.GetHTTPClientTLSInsecureSkipVerify(),
})
// Initialize workers.
state.Workers.Start()
defer state.Workers.Stop()
// Add a task to the scheduler to sweep caches.
// Frequency = 1 * minute
// Threshold = 80% capacity
sweep := func(time.Time) { state.Caches.Sweep(80) }
job := sched.NewJob(sweep).Every(time.Minute)
_ = state.Workers.Scheduler.Schedule(job)
// Build handlers used in later initializations.
mediaManager := media.NewManager(&state)
oauthServer := oauth.New(ctx, dbService)
transportController := transport.NewController(dbService, federatingDB, &federation.Clock{}, client)
federator := federation.NewFederator(dbService, federatingDB, transportController, typeConverter, mediaManager)
typeConverter := typeutils.NewConverter(dbService)
filter := visibility.NewFilter(&state)
federatingDB := federatingdb.New(&state, typeConverter)
transportController := transport.NewController(&state, federatingDB, &federation.Clock{}, client)
federator := federation.NewFederator(&state, federatingDB, transportController, typeConverter, mediaManager)
// decide whether to create a noop email sender (won't send emails) or a real one
// Decide whether to create a noop email
// sender (won't send emails) or a real one.
var emailSender email.Sender
if smtpHost := config.GetSMTPHost(); smtpHost != "" {
// host is defined so create a proper sender
// Host is defined; create a proper sender.
emailSender, err = email.NewSender()
if err != nil {
return fmt.Errorf("error creating email sender: %s", err)
}
} else {
// no host is defined so create a noop sender
// No host is defined; create a noop sender.
emailSender, err = email.NewNoopSender(nil)
if err != nil {
return fmt.Errorf("error creating noop email sender: %s", err)
}
}
// create and start the message processor using the other services we've created so far
processor := processing.NewProcessor(typeConverter, federator, oauthServer, mediaManager, storage, dbService, emailSender, clientWorker, fedWorker)
if err := processor.Start(); err != nil {
return fmt.Errorf("error starting processor: %s", err)
// Initialize timelines.
state.Timelines.Home = timeline.NewManager(
tlprocessor.HomeTimelineGrab(&state),
tlprocessor.HomeTimelineFilter(&state, filter),
tlprocessor.HomeTimelineStatusPrepare(&state, typeConverter),
tlprocessor.SkipInsert(),
)
if err := state.Timelines.Home.Start(); err != nil {
return fmt.Errorf("error starting home timeline: %s", err)
}
idp, err := oidc.NewIDP(ctx)
state.Timelines.List = timeline.NewManager(
tlprocessor.ListTimelineGrab(&state),
tlprocessor.ListTimelineFilter(&state, filter),
tlprocessor.ListTimelineStatusPrepare(&state, typeConverter),
tlprocessor.SkipInsert(),
)
if err := state.Timelines.List.Start(); err != nil {
return fmt.Errorf("error starting list timeline: %s", err)
}
// Create the processor using all the other services we've created so far.
processor := processing.NewProcessor(typeConverter, federator, oauthServer, mediaManager, &state, emailSender)
// Set state client / federator worker enqueue functions
state.Workers.EnqueueClientAPI = processor.EnqueueClientAPI
state.Workers.EnqueueFederator = processor.EnqueueFederator
/*
HTTP router initialization
*/
router, err := router.New(ctx)
if err != nil {
return fmt.Errorf("error creating oidc idp: %s", err)
return fmt.Errorf("error creating router: %s", err)
}
// build web module
webModule := web.New(processor)
// build client api modules
authModule := auth.New(dbService, idp, processor)
accountModule := account.New(processor)
instanceModule := instance.New(processor)
appsModule := app.New(processor)
followRequestsModule := followrequest.New(processor)
webfingerModule := webfinger.New(processor)
nodeInfoModule := nodeinfo.New(processor)
usersModule := user.New(processor)
timelineModule := timeline.New(processor)
notificationModule := notification.New(processor)
searchModule := search.New(processor)
filtersModule := filter.New(processor)
emojiModule := emoji.New(processor)
listsModule := list.New(processor)
mm := mediaModule.New(processor)
fileServerModule := fileserver.New(processor)
adminModule := admin.New(processor)
statusModule := status.New(processor)
securityModule := security.New(dbService, oauthServer)
streamingModule := streaming.New(processor)
favouritesModule := favourites.New(processor)
blocksModule := blocks.New(processor)
userClientModule := userClient.New(processor)
apis := []api.ClientModule{
// modules with middleware go first
securityModule,
authModule,
// now the web module
webModule,
// now everything else
accountModule,
instanceModule,
appsModule,
followRequestsModule,
mm,
fileServerModule,
adminModule,
statusModule,
webfingerModule,
nodeInfoModule,
usersModule,
timelineModule,
notificationModule,
searchModule,
filtersModule,
emojiModule,
listsModule,
streamingModule,
favouritesModule,
blocksModule,
userClientModule,
middlewares := []gin.HandlerFunc{
middleware.AddRequestID(config.GetRequestIDHeader()), // requestID middleware must run before tracing
}
if config.GetTracingEnabled() {
middlewares = append(middlewares, tracing.InstrumentGin())
}
middlewares = append(middlewares, []gin.HandlerFunc{
// note: hooks adding ctx fields must be ABOVE
// the logger, otherwise won't be accessible.
middleware.Logger(config.GetLogClientIP()),
middleware.UserAgent(),
middleware.CORS(),
middleware.ExtraHeaders(),
}...)
for _, m := range apis {
if err := m.Route(router); err != nil {
return fmt.Errorf("routing error: %s", err)
// attach global middlewares which are used for every request
router.AttachGlobalMiddleware(middlewares...)
// attach global no route / 404 handler to the router
router.AttachNoRouteHandler(func(c *gin.Context) {
apiutil.ErrorHandler(c, gtserror.NewErrorNotFound(errors.New(http.StatusText(http.StatusNotFound))), processor.InstanceGetV1)
})
// build router modules
var idp oidc.IDP
if config.GetOIDCEnabled() {
idp, err = oidc.NewIDP(ctx)
if err != nil {
return fmt.Errorf("error creating oidc idp: %w", err)
}
}
routerSession, err := dbService.GetSession(ctx)
if err != nil {
return fmt.Errorf("error retrieving router session for session middleware: %w", err)
}
sessionName, err := middleware.SessionName()
if err != nil {
return fmt.Errorf("error generating session name for session middleware: %w", err)
}
var (
authModule = api.NewAuth(dbService, processor, idp, routerSession, sessionName) // auth/oauth paths
clientModule = api.NewClient(dbService, processor) // api client endpoints
fileserverModule = api.NewFileserver(processor) // fileserver endpoints
wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints
nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint
activityPubModule = api.NewActivityPub(dbService, processor) // ActivityPub endpoints
webModule = web.New(dbService, processor) // web pages + user profiles + settings panels etc
)
// create required middleware
// rate limiting
limit := config.GetAdvancedRateLimitRequests()
clLimit := middleware.RateLimit(limit) // client api
s2sLimit := middleware.RateLimit(limit) // server-to-server (AP)
fsLimit := middleware.RateLimit(limit) // fileserver / web templates
// throttling
cpuMultiplier := config.GetAdvancedThrottlingMultiplier()
retryAfter := config.GetAdvancedThrottlingRetryAfter()
clThrottle := middleware.Throttle(cpuMultiplier, retryAfter) // client api
s2sThrottle := middleware.Throttle(cpuMultiplier, retryAfter) // server-to-server (AP)
fsThrottle := middleware.Throttle(cpuMultiplier, retryAfter) // fileserver / web templates
pkThrottle := middleware.Throttle(cpuMultiplier, retryAfter) // throttle public key endpoint separately
gzip := middleware.Gzip() // applied to all except fileserver
// these should be routed in order;
// apply throttling *after* rate limiting
authModule.Route(router, clLimit, clThrottle, gzip)
clientModule.Route(router, clLimit, clThrottle, gzip)
fileserverModule.Route(router, fsLimit, fsThrottle)
wellKnownModule.Route(router, gzip, s2sLimit, s2sThrottle)
nodeInfoModule.Route(router, s2sLimit, s2sThrottle, gzip)
activityPubModule.Route(router, s2sLimit, s2sThrottle, gzip)
activityPubModule.RoutePublicKey(router, s2sLimit, pkThrottle, gzip)
webModule.Route(router, fsLimit, fsThrottle, gzip)
gts, err := gotosocial.NewServer(dbService, router, federator, mediaManager)
if err != nil {
return fmt.Errorf("error creating gotosocial service: %s", err)
@ -223,22 +278,17 @@ var Start action.GTSAction = func(ctx context.Context) error {
return fmt.Errorf("error starting gotosocial service: %s", err)
}
// perform initial media prune in case value of MediaRemoteCacheDays changed
if err := processor.AdminMediaPrune(ctx, config.GetMediaRemoteCacheDays()); err != nil {
return fmt.Errorf("error during initial media prune: %s", err)
}
// catch shutdown signals from the operating system
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
sig := <-sigs
log.Infof("received signal %s, shutting down", sig)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigs // block until signal received
log.Infof(ctx, "received signal %s, shutting down", sig)
// close down all running services in order
if err := gts.Stop(ctx); err != nil {
return fmt.Errorf("error closing gotosocial service: %s", err)
}
log.Info("done! exiting...")
log.Info(ctx, "done! exiting...")
return nil
}

View file

@ -1,26 +1,26 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package testrig
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
@ -28,152 +28,163 @@ import (
"os/signal"
"syscall"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/api"
"github.com/superseriousbusiness/gotosocial/internal/api/client/account"
"github.com/superseriousbusiness/gotosocial/internal/api/client/admin"
"github.com/superseriousbusiness/gotosocial/internal/api/client/app"
"github.com/superseriousbusiness/gotosocial/internal/api/client/auth"
"github.com/superseriousbusiness/gotosocial/internal/api/client/blocks"
"github.com/superseriousbusiness/gotosocial/internal/api/client/emoji"
"github.com/superseriousbusiness/gotosocial/internal/api/client/favourites"
"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver"
"github.com/superseriousbusiness/gotosocial/internal/api/client/filter"
"github.com/superseriousbusiness/gotosocial/internal/api/client/followrequest"
"github.com/superseriousbusiness/gotosocial/internal/api/client/instance"
"github.com/superseriousbusiness/gotosocial/internal/api/client/list"
mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media"
"github.com/superseriousbusiness/gotosocial/internal/api/client/notification"
"github.com/superseriousbusiness/gotosocial/internal/api/client/search"
"github.com/superseriousbusiness/gotosocial/internal/api/client/status"
"github.com/superseriousbusiness/gotosocial/internal/api/client/streaming"
"github.com/superseriousbusiness/gotosocial/internal/api/client/timeline"
userClient "github.com/superseriousbusiness/gotosocial/internal/api/client/user"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/nodeinfo"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/user"
"github.com/superseriousbusiness/gotosocial/internal/api/s2s/webfinger"
"github.com/superseriousbusiness/gotosocial/internal/api/security"
"github.com/superseriousbusiness/gotosocial/internal/concurrency"
apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gotosocial"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/middleware"
"github.com/superseriousbusiness/gotosocial/internal/oidc"
tlprocessor "github.com/superseriousbusiness/gotosocial/internal/processing/timeline"
"github.com/superseriousbusiness/gotosocial/internal/state"
"github.com/superseriousbusiness/gotosocial/internal/storage"
"github.com/superseriousbusiness/gotosocial/internal/timeline"
"github.com/superseriousbusiness/gotosocial/internal/tracing"
"github.com/superseriousbusiness/gotosocial/internal/visibility"
"github.com/superseriousbusiness/gotosocial/internal/web"
"github.com/superseriousbusiness/gotosocial/testrig"
)
// Start creates and starts a gotosocial testrig server
var Start action.GTSAction = func(ctx context.Context) error {
var state state.State
testrig.InitTestConfig()
testrig.InitTestLog()
dbService := testrig.NewTestDB()
testrig.StandardDBSetup(dbService, nil)
router := testrig.NewTestRouter(dbService)
var storageBackend *storage.Driver
if os.Getenv("GTS_STORAGE_BACKEND") == "s3" {
storageBackend = testrig.NewS3Storage()
} else {
storageBackend = testrig.NewInMemoryStorage()
if err := tracing.Initialize(); err != nil {
return fmt.Errorf("error initializing tracing: %w", err)
}
testrig.StandardStorageSetup(storageBackend, "./testrig/media")
// Create client API and federator worker pools
clientWorker := concurrency.NewWorkerPool[messages.FromClientAPI](-1, -1)
fedWorker := concurrency.NewWorkerPool[messages.FromFederator](-1, -1)
// Initialize caches and database
state.DB = testrig.NewTestDB(&state)
// New test db inits caches so we don't need to do
// that twice, we can just start the initialized caches.
state.Caches.Start()
defer state.Caches.Stop()
testrig.StandardDBSetup(state.DB, nil)
if os.Getenv("GTS_STORAGE_BACKEND") == "s3" {
state.Storage, _ = storage.NewS3Storage()
} else {
state.Storage = testrig.NewInMemoryStorage()
}
testrig.StandardStorageSetup(state.Storage, "./testrig/media")
// Initialize workers.
state.Workers.Start()
defer state.Workers.Stop()
// build backend handlers
oauthServer := testrig.NewTestOauthServer(dbService)
transportController := testrig.NewTestTransportController(testrig.NewMockHTTPClient(func(req *http.Request) (*http.Response, error) {
transportController := testrig.NewTestTransportController(&state, testrig.NewMockHTTPClient(func(req *http.Request) (*http.Response, error) {
r := io.NopCloser(bytes.NewReader([]byte{}))
return &http.Response{
StatusCode: 200,
Body: r,
}, nil
}, ""), dbService, fedWorker)
mediaManager := testrig.NewTestMediaManager(dbService, storageBackend)
federator := testrig.NewTestFederator(dbService, transportController, storageBackend, mediaManager, fedWorker)
}, ""))
mediaManager := testrig.NewTestMediaManager(&state)
federator := testrig.NewTestFederator(&state, transportController, mediaManager)
emailSender := testrig.NewEmailSender("./web/template/", nil)
typeConverter := testrig.NewTestTypeConverter(state.DB)
filter := visibility.NewFilter(&state)
processor := testrig.NewTestProcessor(dbService, storageBackend, federator, emailSender, mediaManager, clientWorker, fedWorker)
if err := processor.Start(); err != nil {
return fmt.Errorf("error starting processor: %s", err)
// Initialize timelines.
state.Timelines.Home = timeline.NewManager(
tlprocessor.HomeTimelineGrab(&state),
tlprocessor.HomeTimelineFilter(&state, filter),
tlprocessor.HomeTimelineStatusPrepare(&state, typeConverter),
tlprocessor.SkipInsert(),
)
if err := state.Timelines.Home.Start(); err != nil {
return fmt.Errorf("error starting home timeline: %s", err)
}
idp, err := oidc.NewIDP(ctx)
if err != nil {
return fmt.Errorf("error creating oidc idp: %s", err)
state.Timelines.List = timeline.NewManager(
tlprocessor.ListTimelineGrab(&state),
tlprocessor.ListTimelineFilter(&state, filter),
tlprocessor.ListTimelineStatusPrepare(&state, typeConverter),
tlprocessor.SkipInsert(),
)
if err := state.Timelines.List.Start(); err != nil {
return fmt.Errorf("error starting list timeline: %s", err)
}
// build web module
webModule := web.New(processor)
processor := testrig.NewTestProcessor(&state, federator, emailSender, mediaManager)
// build client api modules
authModule := auth.New(dbService, idp, processor)
accountModule := account.New(processor)
instanceModule := instance.New(processor)
appsModule := app.New(processor)
followRequestsModule := followrequest.New(processor)
webfingerModule := webfinger.New(processor)
nodeInfoModule := nodeinfo.New(processor)
usersModule := user.New(processor)
timelineModule := timeline.New(processor)
notificationModule := notification.New(processor)
searchModule := search.New(processor)
filtersModule := filter.New(processor)
emojiModule := emoji.New(processor)
listsModule := list.New(processor)
mm := mediaModule.New(processor)
fileServerModule := fileserver.New(processor)
adminModule := admin.New(processor)
statusModule := status.New(processor)
securityModule := security.New(dbService, oauthServer)
streamingModule := streaming.New(processor)
favouritesModule := favourites.New(processor)
blocksModule := blocks.New(processor)
userClientModule := userClient.New(processor)
/*
HTTP router initialization
*/
apis := []api.ClientModule{
// modules with middleware go first
securityModule,
authModule,
// now the web module
webModule,
// now everything else
accountModule,
instanceModule,
appsModule,
followRequestsModule,
mm,
fileServerModule,
adminModule,
statusModule,
webfingerModule,
nodeInfoModule,
usersModule,
timelineModule,
notificationModule,
searchModule,
filtersModule,
emojiModule,
listsModule,
streamingModule,
favouritesModule,
blocksModule,
userClientModule,
router := testrig.NewTestRouter(state.DB)
middlewares := []gin.HandlerFunc{
middleware.AddRequestID(config.GetRequestIDHeader()), // requestID middleware must run before tracing
}
if config.GetTracingEnabled() {
middlewares = append(middlewares, tracing.InstrumentGin())
}
middlewares = append(middlewares, []gin.HandlerFunc{
middleware.Logger(config.GetLogClientIP()),
middleware.UserAgent(),
middleware.CORS(),
middleware.ExtraHeaders(),
}...)
for _, m := range apis {
if err := m.Route(router); err != nil {
return fmt.Errorf("routing error: %s", err)
// attach global middlewares which are used for every request
router.AttachGlobalMiddleware(middlewares...)
// attach global no route / 404 handler to the router
router.AttachNoRouteHandler(func(c *gin.Context) {
apiutil.ErrorHandler(c, gtserror.NewErrorNotFound(errors.New(http.StatusText(http.StatusNotFound))), processor.InstanceGetV1)
})
// build router modules
var idp oidc.IDP
var err error
if config.GetOIDCEnabled() {
idp, err = oidc.NewIDP(ctx)
if err != nil {
return fmt.Errorf("error creating oidc idp: %w", err)
}
}
gts, err := gotosocial.NewServer(dbService, router, federator, mediaManager)
routerSession, err := state.DB.GetSession(ctx)
if err != nil {
return fmt.Errorf("error retrieving router session for session middleware: %w", err)
}
sessionName, err := middleware.SessionName()
if err != nil {
return fmt.Errorf("error generating session name for session middleware: %w", err)
}
var (
authModule = api.NewAuth(state.DB, processor, idp, routerSession, sessionName) // auth/oauth paths
clientModule = api.NewClient(state.DB, processor) // api client endpoints
fileserverModule = api.NewFileserver(processor) // fileserver endpoints
wellKnownModule = api.NewWellKnown(processor) // .well-known endpoints
nodeInfoModule = api.NewNodeInfo(processor) // nodeinfo endpoint
activityPubModule = api.NewActivityPub(state.DB, processor) // ActivityPub endpoints
webModule = web.New(state.DB, processor) // web pages + user profiles + settings panels etc
)
// these should be routed in order
authModule.Route(router)
clientModule.Route(router)
fileserverModule.Route(router)
wellKnownModule.Route(router)
nodeInfoModule.Route(router)
activityPubModule.Route(router)
activityPubModule.RoutePublicKey(router)
webModule.Route(router)
gts, err := gotosocial.NewServer(state.DB, router, federator, mediaManager)
if err != nil {
return fmt.Errorf("error creating gotosocial service: %s", err)
}
@ -186,16 +197,16 @@ var Start action.GTSAction = func(ctx context.Context) error {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
sig := <-sigs
log.Infof("received signal %s, shutting down", sig)
log.Infof(ctx, "received signal %s, shutting down", sig)
testrig.StandardDBTeardown(dbService)
testrig.StandardStorageTeardown(storageBackend)
testrig.StandardDBTeardown(state.DB)
testrig.StandardStorageTeardown(state.Storage)
// close down all running services in order
if err := gts.Stop(ctx); err != nil {
return fmt.Errorf("error closing gotosocial service: %s", err)
}
log.Info("done! exiting...")
log.Info(ctx, "done! exiting...")
return nil
}

View file

@ -1,26 +1,26 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"github.com/spf13/cobra"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/account"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/media"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/media/prune"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action/admin/trans"
"github.com/superseriousbusiness/gotosocial/internal/config"
@ -55,6 +55,18 @@ func adminCommands() *cobra.Command {
config.AddAdminAccountCreate(adminAccountCreateCmd)
adminAccountCmd.AddCommand(adminAccountCreateCmd)
adminAccountListCmd := &cobra.Command{
Use: "list",
Short: "list all existing local accounts",
PreRunE: func(cmd *cobra.Command, args []string) error {
return preRun(preRunArgs{cmd: cmd})
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), account.List)
},
}
adminAccountCmd.AddCommand(adminAccountListCmd)
adminAccountConfirmCmd := &cobra.Command{
Use: "confirm",
Short: "confirm an existing local account manually, thereby skipping email confirmation",
@ -159,17 +171,44 @@ func adminCommands() *cobra.Command {
adminMediaCmd := &cobra.Command{
Use: "media",
Short: "admin commands related stored media attachments/emojis",
Short: "admin commands related to stored media / emojis",
}
/*
ADMIN MEDIA LIST COMMANDS
*/
adminMediaListLocalCmd := &cobra.Command{
Use: "list-local",
Short: "admin command to list media on local storage",
PreRunE: func(cmd *cobra.Command, args []string) error {
return preRun(preRunArgs{cmd: cmd})
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), media.ListLocal)
},
}
adminMediaListRemoteCmd := &cobra.Command{
Use: "list-remote",
Short: "admin command to list remote media cached on this instance",
PreRunE: func(cmd *cobra.Command, args []string) error {
return preRun(preRunArgs{cmd: cmd})
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), media.ListRemote)
},
}
adminMediaCmd.AddCommand(adminMediaListLocalCmd, adminMediaListRemoteCmd)
/*
ADMIN MEDIA PRUNE COMMANDS
*/
adminMediaPruneCmd := &cobra.Command{
Use: "prune",
Short: "admin commands for pruning unused/orphaned media from storage",
Short: "admin commands for pruning media from storage",
}
config.AddAdminMediaPrune(adminMediaPruneCmd)
adminMediaPruneOrphanedCmd := &cobra.Command{
Use: "orphaned",
@ -184,6 +223,32 @@ func adminCommands() *cobra.Command {
config.AddAdminMediaPrune(adminMediaPruneOrphanedCmd)
adminMediaPruneCmd.AddCommand(adminMediaPruneOrphanedCmd)
adminMediaPruneRemoteCmd := &cobra.Command{
Use: "remote",
Short: "prune unused / stale media from storage, older than given number of days",
PreRunE: func(cmd *cobra.Command, args []string) error {
return preRun(preRunArgs{cmd: cmd})
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), prune.Remote)
},
}
config.AddAdminMediaPrune(adminMediaPruneRemoteCmd)
adminMediaPruneCmd.AddCommand(adminMediaPruneRemoteCmd)
adminMediaPruneAllCmd := &cobra.Command{
Use: "all",
Short: "perform all media and emoji prune / cleaning commands",
PreRunE: func(cmd *cobra.Command, args []string) error {
return preRun(preRunArgs{cmd: cmd})
},
RunE: func(cmd *cobra.Command, args []string) error {
return run(cmd.Context(), prune.All)
},
}
config.AddAdminMediaPrune(adminMediaPruneAllCmd)
adminMediaPruneCmd.AddCommand(adminMediaPruneAllCmd)
adminMediaCmd.AddCommand(adminMediaPruneCmd)
adminCmd.AddCommand(adminMediaCmd)

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main

View file

@ -1,28 +1,29 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"log"
"runtime/debug"
"os"
godebug "runtime/debug"
"strings"
"codeberg.org/gruf/go-debug"
"github.com/spf13/cobra"
_ "github.com/superseriousbusiness/gotosocial/docs"
@ -60,9 +61,14 @@ func main() {
// add subcommands
rootCmd.AddCommand(serverCommands())
rootCmd.AddCommand(testrigCommands())
rootCmd.AddCommand(debugCommands())
rootCmd.AddCommand(adminCommands())
if debug.DEBUG {
// only add testrig if debug enabled.
rootCmd.AddCommand(testrigCommands())
} else if len(os.Args) > 1 && os.Args[1] == "testrig" {
log.Fatalln("gotosocial must be built and run with the DEBUG enviroment variable set to enable and access testrig")
}
// run
if err := rootCmd.Execute(); err != nil {
@ -73,7 +79,7 @@ func main() {
// version will build a version string from binary's stored build information.
func version() string {
// Read build information from binary
build, ok := debug.ReadBuildInfo()
build, ok := godebug.ReadBuildInfo()
if !ok {
return ""
}

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main

View file

@ -1,20 +1,19 @@
/*
GoToSocial
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package main

View file

@ -1,26 +0,0 @@
# Admin Control Panel
The GoToSocial admin panel is a simple webclient that uses the [admin api routes](https://docs.gotosocial.org/en/latest/api/swagger/#operations-tag-admin) to manage your instance. It uses the same OAUTH mechanism as normal clients (with scope: admin), and as such can be hosted anywhere, separately from your instance, or run locally. A public installation is available here: [https://gts.superseriousbusiness.org/admin](https://gts.superseriousbusiness.org/admin).
## Using the panel
To use the Admin API your account has to be promoted as such:
```
./gotosocial --config-path ./config.yaml admin account promote --username YOUR_USERNAME
```
After this, you can enter your instance domain in the login field (auto-filled if you run GoToSocial on the same domain), and login like you would with
any other client.
<p align="middle">
<img src="../../assets/admin-panel.png">Screenshot of the GoToSocial admin panel, showing the fields to change an instance's settings</img>
</p>
You can change the instance's settings like the title and descriptions, and add/remove/change domain blocks including a bulk import/export.
## Building the panel
Build requirements: some version of [Node.js](https://nodejs.org) and yarn.
```
yarn install --cwd web/source
BUDO_BUILD=1 node web/source
```
See also: [Contributing.md Stylesheet / Web dev](https://github.com/superseriousbusiness/gotosocial/blob/main/CONTRIBUTING.md#stylesheet--web-dev)

View file

@ -1,18 +1,37 @@
# Backup and Restore
In certain conditions, it may be desirable to be able to back up a GoToSocial instance, and then to restore it again later, or just save the backup somewhere.
As the GoToSocial database contains the instance as well as all user signing keys it is vital to back it up. If you lose these keys you'll never be able to federate from this domain again. Don't forget to also encrypt your backups in order to keep the data safe at rest.
Some potential scenarios:
Aside from disaster recovery, there are other good reasons to keep backups. Some potential scenarios for you to consider:
* You want to close down your instance but you might create it again later and you don't want to break federation.
* You need to migrate to a different database for some reason (Postgres => SQLite or vice versa).
* You want to keep regular backups of your data just in case something happens.
* You want to migrate from GoToSocial to a different Fediverse server, or from a different Fediverse server to GoToSocial.
* You're about to hack around on your instance and you want to make a quick backup so you don't lose everything if you mess up.
There are a few different ways of doing this, most of which require some technical knowledge.
## What to backup
## Image your disk
### Database
Most backup tools have built-in support for common databases like PostgreSQL and SQLite. Ensure you review their documentation first as they often spell out certain considerations and conditions that need to be met for backups to complete and restore successfully.
### Media
Local media should be backed up. You can use the [GoToSocial CLI](cli.md#gotosocial-admin-media-list-local) to list all media files that belong to your instance and its users.
Remote media does not have to be backed up. This can be a good way to keep the size of your backups down. Remote media will be fetched from the origin instance, much like how it'll be fetched again if it got pruned due to media retention.
## How to backup
You can go about this a few different ways:
* Imaging the VMs/machines your instance and database runs on
* Dumping GoToSocial's state with the CLI
* Backing up database and media files
* Backup software
Though setting up backup software can be a bit more work, it's by far the best option. It ensures consistent and encrypted backups and can protect you against filesystem corruption in a way that taking disk snapshots and copying the raw database and media files won't.
### Image your disk
If you're running GoToSocial on a VPS (a remote machine in the cloud), arguably the easiest way to preserve all of your database entries and media is to image the disk attached to the VPS. This will preserve the whole disk. Many VPS providers offer the option of automatically creating backups on a timer, so you'll always be able to restore if your data is lost.
@ -28,24 +47,7 @@ Disadvantages:
* Will probably also preserve stuff you don't need, from other programs running on the same machine.
* Vendor lock-in, difficult to move the data around.
## Back up your database files
Regardless of whether you're using Postgres or SQLite as your GoToSocial database, it's possible to simply back up the database files directly by using something like [rclone](https://rclone.org/), or following best practices for [backing up Postgres data](https://www.postgresql.org/docs/9.1/backup.html) or [SQLite data](https://sqlite.org/backup.html).
Advantages:
* Backups are relatively portable - you can move data from one machine to another.
* Well-documented procedure with a lot of guides and tooling available.
* Lots of different ways of doing your backups, depending on what you need.
Disadvantages:
* Can be a bit fiddly to set up initially.
* You need to figure out where to keep your backups.
* Restoring from backups can be a pain.
* Unless you back up media as well, references to media attachments in your db will be broken.
## Use the GoToSocial CLI
### Use the GoToSocial CLI
The GoToSocial CLI tool also provides commands for backing up and restoring data from your instance, which will preserve the *bare-minimum* necessary data to backup and restore your instance, without breaking federation with other instances.
@ -88,7 +90,7 @@ The backup file produced will be in the form of a line-separated series of JSON
{"type":"instance","id":"01BZDDRPAB8J645ABY31HHF68Y","createdAt":"2021-09-08T10:00:54.763912Z","domain":"localhost:8080","title":"localhost:8080","uri":"http://localhost:8080","reputation":0}
```
For information on how to use the commands to import/export, see [here](cli.md#gotosocial-admin-export).
For information on how to use the commands to import/export, see [here](cli.md#gotosocial-admin-export). Though the `export` command won't backup media, you can use the [`media list-local`](cli.md#gotosocial-admin-media-list-local) command to figure out which media files you should keep.
Advantages:
@ -98,5 +100,123 @@ Advantages:
Disadvantages:
* Loss of statuses/media/etc: don't do a backup/restore this way unless you're willing to drop stuff.
* Loss of statuses/faves/etc: don't do a backup/restore this way unless you're willing to drop stuff.
* You need to use the GtS CLI tool to insert data back into a database, unless you write custom tooling for it.
### Back up your database files and media
Regardless of whether you're using PostgreSQL or SQLite as your GoToSocial database, it's possible to simply back up the database files directly by using something like [rclone](https://rclone.org/), or following best practices for [backing up Postgres data](https://www.postgresql.org/docs/15/backup.html) or [SQLite data](https://sqlite.org/backup.html).
Use the [GoToSocial CLI](cli.md#gotosocial-admin-media-list-local) to get a list of media files you need to safeguard.
Advantages:
* Backups are relatively portable - you can move data from one machine to another.
* Well-documented procedure with a lot of guides and tooling available.
* Lots of different ways of doing your backups, depending on what you need.
Disadvantages:
* Can be a bit fiddly to set up initially.
* You need to figure out where to keep your backups.
* Restoring from backups can be a pain.
* Unless you back up media as well, references to media attachments in your db will be broken.
### Backup software
Backup software is created with the specific purpose of helping you create, manage and restore your backups. It typically knows how to safely backup your database so you don't have to be an expert on how to do PostgreSQL or SQLite backups. It can backup from the filesystem too.
Though the same advantages and disadvantages roughly apply as with backing up the database files directly, this approach does have some nice extras:
* Backups are highly portable and can be used to restore the database from 0
* Backups happen on a regular schedule and with configurable retention policies
* Backups are incremental and compressed to save on storage and bandwidth
* Backups are encrypted
* Built-in tooling to list your snapshots and restore from them
!!! tip
[Rsync.net](https://rsync.net/), [BorgBase](https://www.borgbase.com/) and [Hetzner Storage](https://www.hetzner.com/storage/storage-box) provide affordable storage that you can use as a backup target. Rsync.net has a special Borg-only backup product that is much cheaper than their regular storage product. If you only want to use them for backups managed with Borg, [sign up here instead](https://www.rsync.net/products/borg.html).
#### Borgmatic
[Borgmatic](https://torsion.org/borgmatic/) is a utility to help perform backups using [Borg](https://www.borgbackup.org/). It's driven by a declarative configuration file using YAML. BorgBase, Rsync.net and Hetzner all support Borg.
!!! warning
When initialising the Borg repository, ensure you set it up with a strong encryption key and store that key somewhere safely. Without it you won't be able to decrypt your backups in the future. The ArchWiki entry on Borgmatic explains how to safely pass your encryption key to Borgmatic without storing it plain text in its configuration file.
How to backup databases with Borgmatic has its own [documentation page](https://torsion.org/borgmatic/docs/how-to/backup-your-databases/) that you should review. A simple `config.yaml` for Borgmatic with GoToSocial using SQLite looks like this:
```yaml
location:
repositories:
- path: ssh://<find it in your provider control panel>
label: <anything but typically the provider, for example borgbase>
patterns_from:
- /etc/borgmatic/gotosocial_patterns
storage:
compression: auto,zstd
archive_name_format: '{hostname}-{now:%Y-%m-%d-%H%M%S}'
retries: 5
retry_wait: 30
retention:
keep_daily: 7
keep_weekly: 6
keep_monthly: 12
hooks:
before_backup:
- /usr/bin/systemctl stop gotosocial
after_backup:
- /usr/bin/systemctl start gotosocial
sqlite_databases:
- name: gotosocial
path: /path/to/sqlite.db
```
For PostgreSQL, you'll want to use `postgresql_databases` instead.
The file mentioned in `patterns_from` can be created by transforming the output from the [GoToSocial CLI](cli.md#gotosocial-admin-media-list-local). In order to generate the right patterns you can use the [`media-to-borg-patterns.py`](https://github.com/superseriousbusiness/gotosocial/tree/main/example/borgmatic/media-to-borg-patterns.py) script. How Borg patterns work is explained in [their documentation](https://man.archlinux.org/man/borg-patterns.1).
You'll need to put that file on your GoToSocial instance and make sure the file is executable. It requires Python 3 which you will already have if you have Borg and Borgmatic installed. It only depends on the Python standard library.
!!! note
For this to work reliably, you should ensure that the [storage-local-base-path](../configuration/storage.md) in your GoToSocial configuration uses an absolute path. Otherwise you'll have to tweak the paths yourself.
```sh
$ gotosocial admin media list-local | \
/path/to/media-to-borg-patterns.py \
<storage-local-base-path>
```
This will output a pattern set looking roughly like this to your console:
```
R <storage-local-base-path>
+ pp:<storage-local-base-path>/<account ID>
- <storage-local-base-path>/*
```
!!! tip
You can view the help by passing `--help` to `media-to-borg-patterns.py`. It can write the output to a file directly by passing the location of a file as the last argument to the script.
Given this set of patterns, Borg will start looking for files starting from `<storage-local-base-path>`. Anything that matches the path prefix, `pp:` will be included. Everything else will match the last pattern, excluding it from the archive.
On a single-user instance, you can run this command once and inline the patterns directly in your Borgmatic configuration [using the `patterns` key](https://torsion.org/borgmatic/docs/reference/configuration/). On multi-user instances you should run this after a user signs up. Alternatively, you can run it every time before you do a backup.
If you're running Borgmatic as a systemd service, you can [create a drop-in](https://wiki.archlinux.org/title/systemd#Drop-in_files) for `borgmatic.service` and run the pattern generation before the backup is started with:
```ini
[Service]
ExecStartPre=/path/to/gotosocial admin media list-local | /path/to/media-to-borg-patterns.py <storage-local-base-path> /etc/borgmatic/gotosocial_patterns
```
Documentation that's good to review:
* Borgmatic [configuration reference](https://torsion.org/borgmatic/docs/reference/configuration/)
* ArchWiki entry [on Borgmatic](https://wiki.archlinux.org/title/Borgmatic)
* ArchWiki entry [on Borg](https://wiki.archlinux.org/title/Borg_backup)
* BorgBase [documentation](https://docs.borgbase.com/)
* Hetzner community guide on [setting up Borgmatic](https://community.hetzner.com/tutorials/install-and-configure-borgmatic)

View file

@ -179,7 +179,7 @@ Flags:
Example:
```bash
gotosocial admin account password --username some_username --pasword some_really_good_password --config-path config.yaml
gotosocial admin account password --username some_username --password some_really_good_password --config-path config.yaml
```
### gotosocial admin export
@ -255,6 +255,18 @@ Example:
gotosocial admin import --path example.json --config-path config.yaml
```
### gotosocial admin media list-local
This command can be used to list local media. Local media is media that belongs to posts by users with an account on the instance.
The output will be a list of files. The list can be used to drive your backups.
### gotosocial admin media list-remote
This is the corollary to list-local, but instead lists media from remote instances. Remote media belongs to other instances, but was attached to a post we received over federation and have potentially cached locally.
The output will be a list of URLs to retrieve the original content from. GoToSocial automatically retrieves remote media when it needs it, so you should never need to do so yourself.
### gotosocial admin media prune orphaned
This command can be used to prune orphaned media from your GoToSocial.
@ -287,3 +299,40 @@ Example (for real):
```bash
gotosocial admin media prune orphaned --dry-run=false
```
### gotosocial admin media prune remote
This command can be used to prune unused/stale remote media from your GoToSocial.
Stale media means avatars/headers/status attachments from remote instances that are older than `media-remote-cache-days`.
These items will be refetched later on demand, if necessary.
Unused media means avatars/headers/status attachments which are not currently in use by an account or status.
**This command only works when GoToSocial is not running, since it acquires an exclusive lock on storage. Stop GoToSocial first before running this command!**
```text
prune unused/stale remote media from storage, older than given number of days
Usage:
gotosocial admin media prune remote [flags]
Flags:
--dry-run perform a dry run and only log number of items eligible for pruning (default true)
-h, --help help for remote
```
By default, this command performs a dry run, which will log how many items can be pruned. To do it for real, add `--dry-run=false` to the command.
Example (dry run):
```bash
gotosocial admin media prune remote
```
Example (for real):
```bash
gotosocial admin media prune remote --dry-run=false
```

57
docs/admin/settings.md Normal file
View file

@ -0,0 +1,57 @@
# Admin Settings
The GoToSocial Settings interface uses the [admin api routes](https://docs.gotosocial.org/en/latest/api/swagger/#operations-tag-admin) to manage your instance. It's combined with the [User settings](../user_guide/settings.md) and uses the same OAUTH mechanism as normal clients (with scope: admin).
## Account permissions
To use the Admin API your account has to be promoted as such:
```
./gotosocial --config-path ./config.yaml admin account promote --username YOUR_USERNAME
```
After this, you can enter your instance domain in the login field (auto-filled if you run GoToSocial on the same domain), and login like you would with any other client.
## Instance Settings
![Screenshot of the GoToSocial admin panel, showing the fields to change an instance's settings](../assets/admin-settings.png)
Here you can set various metadata for your instance, like the displayed name, thumbnail image, description texts (HTML), and contact username and email.
## Actions
You can use media cleanup to remove remote media older than the specified number of days. This also removes unused headers and avatars.
## Federation
![List of suspended instances, with a field to filter/add new blocks. Below is a link to the bulk import/export interface](../assets/admin-settings-federation.png)
In the federation section you can influence which instances you federate with, through adding domain blocks. You can enter a domain to suspend in the search field, which will filter the list to show you if you already have a block for it. Clicking 'suspend' gives you a form to add a public and/or private comment, and submit to add the block. Adding a suspension will suspend all the currently known accounts on the instance, and prevent any new interactions with any user on the blocked instance.
### Bulk import/export
Through the link at the bottom of the Federation section (or going to `/settings/admin/federation/import-export`) you can do bulk import/export of your domain blocklist.
![List of domains included in an import, providing ways to select some or all of them, change their domains, and update the use of subdomains.](../assets/admin-settings-federation-import-export.png)
Upon importing a list, either through the input field or from a file, you can review the entries in the list before importing a subset. You'll also be warned for entries that use subdomains, providing an easy way to change them to the main domain.
## Reports
![List of reports for testing, one resolved and one open.](../assets/admin-settings-reports.png)
The reports section shows a list of reports, originating from your local users, or remote instances (shown anonymously as just the name of the instance, without specific username).
Clicking a report shows if it was resolved (with the reasoning if available), more information, and a list of reported toots if selected by the reporting user.
## Custom Emoji
Custom Emoji will be automatically fetched when included in remote toots, but to use them in your own posts they have to be enabled on your instance.
### Local
![Local custom emoji section, showing an overview of custom emoji sorted by category. There are a lot of garfields.](../assets/admin-settings-emoji-local.png)
This section shows an overview of all the custom emoji enabled on your instance, sorted by their category. Clicking an emoji shows it's details, and provides options to change the category or image, or delete it completely. The shortcode cannot be updated here, you would have to upload it with the new shortcode yourself (and optionally delete the old one).
Below the overview you can upload your own custom emoji, after previewing how they look in a toot. PNG and (animated) GIF's are supported.
### Remote
![Remote custom emoji section, showing a list of 3 emoji parsed from the entered toot, garfield, blobfoxbox and blobhajmlem. They can be selected, their shortcode can be tweaked, and they can be assigned to a category, before submitting as a copy or delete operation](../assets/admin-settings-emoji-remote.png)
Through the 'remote' section, you can look up a link to any remote toots (provided the instance isn't suspended). If they use any custom emoji they will be listed, providing an easy way to copy them to the local emoji (for use in your own toots), or disable them ( hiding them from toots).
**Note:** as the testrig server does not federate, this feature can't be used in development (500: Internal Server Error).

View file

@ -0,0 +1,86 @@
# Caching API responses
It is possible to cache certain API responses to offload the GoToSocial process from having to handle all requests. We don't recommend caching responses to requests under `/api`.
When using a [split domain](../host-account-domain.md) deployment style, you need to ensure you configure caching on the host domain. The account domain should only be issuing redirects to the host domain which clients will automatically remember.
!!! warning "There are only two hard things in computer science"
Configuring caching incorrectly can result into all kinds of problems. Follow this guide carefully and thoroughly test your modifications. Don't cache endpoints that require authentication without taking the `Authorization` header into account.
## Endpoints
### Webfinger and hostmeta
Requests to `/.well-known/webfinger` and `/.well-known/host-meta` can be safely cached. Do be careful to ensure any caching strategy takes query parameters into account when caching webfinger requests as requests to that endpoint are of the form `?resource=acct:@username@domain.tld`.
### Public keys
Many implementations will regularly request the public key for a user in order to validate the signature on a message they received. This will happen whenever a message gets federated amongst other things. These keys are long lived, essentially eternal, and can thus be cached with a long lifetime.
## Configuration snippets
### nginx
For nginx, you'll need to start by configuring a cache zone. The cache zone must be created in the `http` section, not within `server` or `location`.
```nginx
http {
...
proxy_cache_path /var/cache/nginx keys_zone=gotosocial_ap_public_responses:10m inactive=1w;
}
```
This configures a cache of 10MB whose entries will be kept up to one week if they're not accessed.
The zone is named `gotosocial_ap_public_responses` but you can name it whatever you want. 10MB is a lot of cache keys; you can probably use a smaller value on small instances.
Second, we need to update our GoToSocial nginx configuration to actually use the cache for the endpoints we want to cache.
```nginx
server {
server_name social.example.org;
location ~ /.well-known/(webfinger|host-meta)$ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache gotosocial_ap_public_responses;
proxy_cache_background_update on;
proxy_cache_key $scheme://$host$uri$is_args$query_string;
proxy_cache_valid 200 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://localhost:8080;
}
location ~ ^\/users\/(?:[a-z0-9_\.]+)\/main-key$ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache gotosocial_ap_public_responses;
proxy_cache_background_update on;
proxy_cache_key $scheme://$host$uri;
proxy_cache_valid 200 604800s;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_429;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://localhost:8080;
}
```
The `proxy_pass` and `proxy_set_header` are mostly the same, but the `proxy_cache*` entries warrant some explanation:
- `proxy_cache gotosocial_ap_public_responses` tells nginx to use the `gotosocial_ap_public_responses` cache zone we previously created. If you named it something else, you should change this value
- `proxy_cache_background_update on` means nginx will try and refresh a cached resource that's about to expire in the background, to ensure it has a current copy on disk
- `proxy_cache_key` is configured in such a way that it takes the query string into account for caching. So a request for `.well-known/webfinger?acct=user1@example.org` and `.well-known/webfinger?acct=user2@example.org` are not seen as the same.
- `proxy_cache_valid 200 10m;` means we only cache 200 responses from GTS and for 10 minutes. You can add additional lines of these, like `proxy_cache_valid 404 1m;` to cache 404 responses for 1 minute
- `proxy_cache_use_stale` tells nginx it's allowed to use a stale cache entry (so older than 10 minutes) in certain cases
- `proxy_cache_lock on` means that if a resource is not cached and there's multiple concurrent requests for them, the queries will be queued up so that only one request goes through and the rest is then answered from cache
- `add_header X-Cache-Status $upstream_cache_status` will add an `X-Cache-Status` header to the response so you can check if things are getting cached. You can remove this.
The provided configuration will serve a stale response in case there's an error proxying to GoToSocial, if our connection to GoToSocial times out, if GoToSocial returns a `5xx` status code or if GoToSocial returns 429 (Too Many Requests). The `updating` value says that we're allowed to serve a stale entry if nginx is currently in the process of refreshing its cache. Because we configured `inactive=1w` in the `proxy_cache_path` directive, nginx may serve a response up to one week old if the conditions in `proxy_cache_use_stale` are met.

View file

@ -0,0 +1,143 @@
# Caching assets and media
When you've configured your GoToSocial instance with local storage for media, you can use your [reverse proxy](../../getting_started/reverse_proxy/index.md) to serve these files directly and cache them. This avoids hitting GoToSocial for these requests and reverse proxies can typically serve assets faster than GoToSocial.
You can also use your reverse proxy to cache the GoToSocial web UI assets, like the CSS and images it uses.
When using a [split domain](../host-account-domain.md) deployment style, you need to ensure you configure caching of the assets and media on the host domain.
!!! warning "Media pruning"
If you've configured media pruning, you need to ensure that when media is not found on disk the request is still sent on to GoToSocial. This will ensure the media is fetched again from the remote instance and subsequent requests for this media will then be handled by your reverse proxy again.
## Endpoints
There are 2 endpoints that serve assets we can serve and cache:
* `/assets` which contains fonts, CSS, images etc. for the web UI
* `/fileserver` which serves attachments for status posts when using the local storage backend
The filesystem location of `/assets` is defined by the [`web-asset-base-dir`](../../configuration/web.md) configuration option. Files under `/fileserver` are retrieved from the [`storage-local-base-path`](../../configuration/storage.md).
## Configuration
### Apache 2.4
This is intended to behave identical to the nginx section below.
The `Cache-Control` header is manually set to merge the values
from the configuration and the `expires` directive to avoid
breakage from having two header lines. `Header set` defaults
to ` onsuccess`, so it is also not added to error responses.
Assuming your GtS installation is rooted in `/opt/GtS` with a
`storage` subdirectory, and the webserver has been given access,
add the following section to the vhost:
```
<Directory /opt/GtS/web/assets>
Options None
AllowOverride None
Require all granted
ExpiresActive on
ExpiresDefault A300
Header set Cache-Control "public, max-age=300"
</Directory>
RewriteRule "^/assets/(.*)$" "/opt/GtS/web/assets/$1" [L]
<Directory /opt/GtS/storage>
Options None
AllowOverride None
Require all granted
ExpiresActive on
ExpiresDefault A604800
Header set Cache-Control "private, immutable, max-age=604800"
</Directory>
RewriteCond "/opt/GtS/storage/$1" -f
RewriteRule "^/fileserver/(.*)$" "/opt/GtS/storage/$1" [L]
```
The trick here is that, in an Apache 2-based reverse proxy setup…
```
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://localhost:8980/$1" [P,L]
ProxyIOBufferSize 65536
ProxyTimeout 120
ProxyPreserveHost On
<Location "/">
ProxyPass http://127.0.0.1:8980/
ProxyPassReverse http://127.0.0.1:8980/
</Location>
```
… everything is proxied by default, the `RewriteRule` bypasses
the proxy (by specifying a filesystem path to redirect to) for
specific URL præficēs and the `RewriteCond` ensures to only
disable the `/fileserver/` proxy if the file is, indeed, present.
Also run the following commands (assuming a Debian-like setup)
to enable the modules used:
```
$ sudo a2enmod expires
$ sudo a2enmod headers
$ sudo a2enmod rewrite
```
Then (after a configtest), restart Apache.
### nginx
Here's an example of the three location blocks you'll need to add to your existing configuration in nginx:
```nginx
server {
server_name social.example.org;
location /assets/ {
alias web-asset-base-dir/;
autoindex off;
expires 5m;
add_header Cache-Control "public";
}
location @fileserver {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /fileserver/ {
alias storage-local-base-path/;
autoindex off;
expires 1w;
add_header Cache-Control "private, immutable";
try_files $uri @fileserver;
}
}
```
The `/fileserver` location is a bit special. When we fail to fetch the media from disk, we want to proxy the request on to GoToSocial so it can try and fetch it. The `try_files` directive can't take a `proxy_pass` itself so instead we created the named `@fileserver` location that we pass in last to `try_files`.
!!! bug "Trailing slashes"
The trailing slashes in the `location` directives and the `alias` are significant, do not remove those.
The `expires` directive adds the necessary headers to inform the client how long it may cache the resource:
* For assets, which may change on each release, 5 minutes is used in this example
* For attachments, which should never change once they're created, we currently use one week
For other options, see the nginx documentation on the [`expires` directive](https://nginx.org/en/docs/http/ngx_http_headers_module.html#expires).
Nginx does not add cache headers to 4xx or 5xx response codes so a failure to fetch an asset won't get cached by clients. The `autoindex off` directive tells nginx to not serve a directory listing. This should be the default but it doesn't hurt to be explicit. The added `add_header` lines set additional options for the `Cache-Control` header:
* `public` is used to indicate that anyone may cache this resource
* `immutable` is used to indicate this resource will never change while it is fresh (it's before the end of the expires) allowing clients to forgo conditional requests to revalidate the resource during that timespan.

View file

@ -0,0 +1,11 @@
# Caching
This section covers a number of different caching techniques that can be used to make GoToSocial more robust in the face of higher traffic and offload the GoToSocial instance from some work.
!!! note
These guides are only relevant if you're running a [reverse proxy](../../getting_started/reverse_proxy/index.md).
## Guides
* [Caching API responses](api.md)
* [Assets and media serving and caching](assets-media.md)

View file

@ -0,0 +1,108 @@
# Provisioning TLS certificates
As explained in the [deployment considerations](../getting_started/index.md), federation requires the use of TLS as most instances refuse to federate over unencrypted transports.
GoToSocial comes with built-in support for provisioning and renewing its own TLS certificates through Lets Encrypt. This guide looks at how you can provision your own certificates independently from GoToSocial. This can be useful if you want full control over how the certificates are provisioned, or because you're using a [reverse proxy](../getting_started/reverse_proxy/index.md) which is doing TLS termination.
There are a few different ways you can get TLS certificates:
* Buy them from a vendor, typically valid for 2 years
* Get them from your cloud provider, validity depends on their product constraints
* Get them from an [ACME](https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment)-compatible provider like Lets Encrypt, typically valid for 3 months at a time
In this guide we'll only look at option 3, an ACME-compatible vendor.
## General approach
The way you'll provision certificates through Lets Encrypt is:
* Install an ACME client on your server
* Configure the ACME client to provision your certificates
* Configure a piece of software to use those certificates
* Enable a timer/cron to regularly renew the certificates
* Signal to the necessary applications they need to reload or restart to pick up the new certificates
Certificates are provisioned [using a challenge](https://letsencrypt.org/sv/docs/challenge-types/), a way to verify that you're requesting a certificate for a domain you control. You'll typically use one of:
* HTTP challenge
* DNS challenge
The HTTP challenge requires serving certain files on port 80 on the domains you're requesting a certificate for under the `/.well-known/acme/` path. This is the default challenge type.
The DNS challenge happens entirely out of band but requires you to update a DNS TXT record. This approach is only feasible if your DNS registrar provides an API through which you can modify DNS records so that your ACME client can complete this challenge.
## Clients
The official Lets Encrypt client is [certbot](https://certbot.eff.org/) and it's usually packaged in [your (Linux) distribution](https://repology.org/project/certbot/versions) of choice. Certain reverse proxies like Caddy and Traefik have built-in support for provisioning certificates using the ACME protocol.
A couple of other clients of note that you can consider using:
* [acme-client](https://man.openbsd.org/acme-client.1) for OpenBSD using the privilege separation features of the platform
* [lacme](https://git.guilhem.org/lacme/about/), which is built with process isolation and minimal privileges in mind in the same vein as acme-client but for Linux
* [Lego](https://github.com/go-acme/lego), an ACME client and library written in Go
* [mod_md](https://httpd.apache.org/docs/2.4/mod/mod_md.html), when using Apache 2.4.30+
### DNS challenge
For the DNS challenge, the API of your registrar needs to be supported by your ACME client. Though certbot has a few plugins for popular providers, you probably want to look at the [dns-multi](https://github.com/alexzorin/certbot-dns-multi) plugin instead. It leverages [Lego](https://github.com/go-acme/lego) under the hood which supports a much wider array of providers.
## Configuration
There are 3 configuration options that are important:
* [`letsencrypt-enabled`](../configuration/tls.md) controls if GoToSocial will try to provision its own certificates
* [`tls-certificate-chain`](../configuration/tls.md) filesystem path where GoToSocial can find the TLS certificate chain + the public key
* [`tls-certificate-key`](../configuration/tls.md) filesystem path where GoToSocial can find the associated TLS private key
### Without reverse proxy
When running GoToSocial directly exposed to the internet, but you still want to use your own certificates you can set the following options:
```yaml
letsencrypt-enabled: false
tls-certificate-chain: "/path/to/combined-certificate-chain-public.key"
tls-certificate-key: "/path/to/private.key"
```
This disables the built-in provisioning of certificates through Lets Encrypt and tells GoToSocial where to find the certificates on disk.
!!! tip
Restart GoToSocial after renewing your certificates. It won't pick up on certificate rotation by itself when they are provided like this.
### With reverse proxy
When running GoToSocial behind a [reverse proxy](../getting_started/reverse_proxy/index.md) which you also use for TLS termination, you'll need the following instead:
```yaml
letsencrypt-enabled: false
tls-certificate-chain: ""
tls-certificate-key: ""
```
It's important to ensure the `tls-certificate-*` options are unset or set to the empty string. Otherwise GoToSocial will attempt to handle TLS itself.
!!! danger "Protocol configuration option"
Do **not** change the [`protocol`](../configuration/general.md) configuration option to `http`. This should only ever by set to `http` for development purposes. It needs to be set to `https` even when running behind a TLS-terminating reverse proxy.
You'll also want to change the [`port`](../configuration/general.md) GoToSocial binds on, so it no longer tries to use port 443.
To configure TLS in your reverse proxy, please refer to their documentation:
* [nginx](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-http/)
* [apache](https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html)
* [Traefik](https://doc.traefik.io/traefik/https/tls/)
* [Caddy](https://caddyserver.com/docs/caddyfile/directives/tls)
!!! tip
When configuring TLS in your reverse proxy, ensure you configure a reasonably modern set of compatible versions and ciphers. You can use the "Intermediate" configuration from the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/).
Check the documentation of your reverse proxy on whether you have to reload or restart it after certificates have changed. Not all reverse proxies detect this.
## Guides
There are a number of good resources on the internet explaining how to set all of this up.
* [ArchWiki entry](https://wiki.archlinux.org/title/certbot) on certbot
* [Gentoo wiki entry](https://wiki.gentoo.org/wiki/Let%27s_Encrypt) on Lets Encrypt
* [Linode guide](https://www.linode.com/docs/guides/enabling-https-using-certbot-with-nginx-on-fedora/) on certbot for Fedora, RHEL/CentOS, Debian and Ubuntu
* Digital Ocean guides on Lets Encrypt on Ubuntu 22.04 with [nginx](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-22-04) or [apache](https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-22-04)

View file

@ -0,0 +1,104 @@
# Split-domain deployments
This guide explains how to have usernames like `@me@example.org` but run the GoToSocial instance itself on a subdomain like `social.example.org`. Configuring this type of deployment layout **must** be done before starting GoToSocial for the first time.
!!! danger
You cannot change your domain layout after you've federated with someone. Servers are going to get confused and you'll need to convince the admin of every instance that's federated with you before to mess with their database to resolve it. It also requires regenerating the database on your side to create a new instance account and pair of encryption keys.
## Background
The way ActivityPub implementations discover how to map your account domain to your host domain is through a protocol called [webfinger](https://www.rfc-editor.org/rfc/rfc7033). This mapping is typically cached by servers and hence why you can't change it after the fact.
It works by doing a request to `https://<account domain>/.well-known/webfinger?resource=acct:@me@example.org`. At this point, a server can return a redirect to where the actual webfinger endpoint is, `https://<host domain>/.well-known/webfinger?resource=acct:@me@example.org` or may respond directly. The JSON document that is returned informs you what the endpoint to query is for the user:
```json
{
"subject": "acct:me@example.org",
"aliases": [
"https://social.example.org/users/me",
"https://social.example.org/@me"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://social.example.org/@me"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://social.example.org/users/me"
}
]
}
```
ActivityPub clients and servers will now use the entry from the `links` array with `rel` `self` and `type` `application/activity+json` to query for further information, like where the `inbox` is located to federated messages to.
## Configuration
There are 2 configuration settings you'll need to concern yourself with:
* `host`, the domain the API will be served on and what clients and servers will end up using when talking to your instance
* `account-domain`, the domain user accounts will be created on
In order to achieve the setup as described in the introduction, you'll need to set these two configuration options accordingly:
```yaml
host: social.example.org
account-domain: example.org
```
!!! info
The `host` must always be the DNS name that your GoToSocial instance runs on. It does not affect the IP address the GoToSocial instance binds to. That is controlled with `bind-address`.
## Reverse proxy
When using a [reverse proxy](../getting_started/reverse_proxy/index.md) you'll need to ensure you're set up to handle traffic on both of those domains. You'll need to redirect a few endpoints from the account domain to the host domain.
Redirects are typically used so that the change of domain can be detected client side. The endpoints to redirect from the account domain to the host domain are:
* `/.well-known/webfinger`
* `/.well-known/host-meta`
* `/.well-known/nodeinfo`
!!! tip
Do not proxy or redirect requests to the API endpoints, `/api/...`, from the account domain to the host domain. This will confuse heuristics some clients use to detect a split-domain deployment resulting in broken login flows and other weird behaviour.
### nginx
In order to configure the redirect, you'll need to configure it on the account domain. Assuming the account domain is `example.org` and the host domain is `social.example.org`, the following configuration snippet showcases how to do this:
```nginx
server {
server_name example.org;
location /.well-known/webfinger {
rewrite ^.*$ https://social.example.org/.well-known/webfinger permanent;
}
location /.well-known/host-meta {
rewrite ^.*$ https://social.example.org/.well-known/host-meta permanent;
}
location /.well-known/nodeinfo {
rewrite ^.*$ https://social.example.org/.well-known/nodeinfo permanent;
}
}
```
### Traefik
If `example.org` is running on [Traefik](https://doc.traefik.io/traefik/), we could use labels similar to the following to setup the redirect.
```yaml
myservice:
image: foo
# Other stuff
labels:
- 'traefik.http.routers.myservice.rule=Host(`example.org`)'
- 'traefik.http.middlewares.myservice-gts.redirectregex.permanent=true'
- 'traefik.http.middlewares.myservice-gts.redirectregex.regex=^https://(.*)/.well-known/(webfinger|nodeinfo|host-meta)$$'
- 'traefik.http.middlewares.myservice-gts.redirectregex.replacement=https://social.$${1}/.well-known/$${2}'
- 'traefik.http.routers.myservice.middlewares=myservice-gts@docker'
```

16
docs/advanced/index.md Normal file
View file

@ -0,0 +1,16 @@
# Advanced
In this section we touch on a number of more advanced topics, primarily related around deploying, operating and tuning GoToSocial.
We consider these topics advanced because applying them incorrectly does have the possibility of causing client and federation issues. Applying any of these configuration changes may also make it harder for you to debug an issue with your GoToSocial instance if you don't understand the changes that you're making.
## Guides
* [Split-domain deployment (API vs. account domain)](host-account-domain.md)
* [Using an HTTP proxy for client/outgoing requests](outgoing-proxy.md)
* [Provisioning TLS certificates](certificates.md)
* [Caching API responses](caching/api.md)
* [Serving and caching assets and media from local storage](caching/assets-media.md)
* [Process sandboxing](security/sandboxing.md)
* [Firewall configuration](security/firewall.md)
* [Tracing](tracing.md)

View file

@ -0,0 +1,21 @@
# Outgoing HTTP proxy
GoToSocial supports canonical environment variables for configuring the use of an HTTP proxy for outgoing requets:
* `HTTP_PROXY`
* `HTTPS_PROXY`
* `NO_PROXY`
The lowercase versions of these environment variables are also recognised. `HTTPS_PROXY` takes precedence over `HTTP_PROXY` for https requests.
The environment values may be either a complete URL or a `host[:port]`, in which case the "http" scheme is assumed. The schemes "http", "https", and "socks5" are supported.
## systemd
When running with systemd, you can add the necessary environment variables using the `Environment` option in the `Service` section.
How to do so is documented in the [`systemd.exec` manual](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment).
## Container runtime
Environment variables can be set in the compose file under the `environment` key. You can also pass them on the CLI to Docker or Podman's `run` command with `-e KEY=VALUE` or `--env KEY=VALUE`.

View file

@ -0,0 +1,84 @@
# Firewall
You should deploy a firewall on your instance to close off any open ports and give you a mechanism to ban potentially misbehaving clients. Many firewall frontends will also automatically install some rules that block obvious malicious packets.
It can be helpful to deploy tools that monitor your log files for certain patterns and automatically ban clients exhibiting certain behaviour. This can be use to monitor your SSH and web server access logs for things like SSH brute-force attacks.
## Ports
For GoToSocial, you'll want to ensure port `443` remains open. Without it, nobody will be able to reach your instance. Federation will fail and client apps won't be able to work at all.
If you [provision TLS certificates](../certificates.md) using ACME or GoToSocial's built-in Lets Encrypt support, you'll also need port `80` to be open.
In order to access your instance over SSH, you'll need to keep the port your SSH daemon is bound on open too. By default this is port `22`.
## ICMP
[Internet Control Message Protocol](https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol) are exchanged between machines in order to detect certain network conditions or troubleshoot things. Many firewalls have a tendency of blocking ICMP entirely but this is undesirable. A few ICMP types should be allowed and you can use your firewall to configure rate limiting for them instead.
### IPv4
In order for things to work reliably, your firewall must allow:
* ICMP Type 3: "Destination Unreachable" and also aids in Path-MTU Discovery
* ICMP Type 4: "Source Quench"
If you want to be able to ping things or be pinged, you should also allow:
* ICMP Type 0: "Echo Reply"
* ICMP Type 8: "Echo Request"
For traceroute to work, it can be helpful to also allow:
* ICMP Type 11: "Time Exceeded"
### IPv6
ICMP is heavily relied on by all parts of the IPv6 stack and things will break in exciting and hard to debug ways if you block it. [RFC 4890](https://www.rfc-editor.org/rfc/rfc4890) was specifically written to address this and is worthwhile to review.
Roughly speaking, you must always allow:
* ICMP Type 1: "Destination Unreachable"
* ICMP Type 2: "Packet Too Big"
* ICMP Type 3, code 0: "Time Exceeded"
* ICMP Type 4, code 1, 2: "Parameter Problem"
For ping, you should allow:
* ICMP Type 128: "Echo Request"
* ICMP Type 129: "Echo Response"
## Firewall configuration
On Linux, firewalling is typically done using either [iptables](https://en.wikipedia.org/wiki/Iptables) or the more modern and faster [nftables](https://en.wikipedia.org/wiki/Nftables) as the backend. Most distributions are switching to nftables and many firewall frontends can be configured to use nftables instead. You'll need to refer to your distribution's documentation on the matter, but typically there will be an `iptables` or `nftables` service your init-system can start with a predefined location to load firewall rules from.
Doing this by hand using raw iptables or nftables rules offers the most control but can be challenging if you're not familiar with these systems. In order to help with that, a number of configuration frontends exist that you can use.
On the Debian and Ubuntu as well as openSUSE family of distributions, UFW is commonly used. It's a simple firewall front-end and many tutorials targeting those distributions will be using it.
For the Red Hat/CentOS family of distributions, firewalld is typically used. It's a much more advanced firewall configuration utility which also has a desktop GUI and [Cockpit integration](https://cockpit-project.org/).
Despite distribution preferences, you can use UFW, firewalld or something else entirely with any Linux distribution.
* [Ubuntu Wiki](https://wiki.ubuntu.com/UncomplicatedFirewall?action=show&redirect=UbuntuFirewall) on UFW
* [ArchWiki](https://wiki.archlinux.org/title/Uncomplicated_Firewall) on UFW
* Digital Ocean guide on [using UFW with Ubuntu 22.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-22-04)
* [firewalld](https://firewalld.org/) project homepage and documentation
* [ArchWiki](https://wiki.archlinux.org/title/firewalld) on firewalld
* [Using and configuring firewalld](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/configuring_firewalls_and_packet_filters/using-and-configuring-firewalld_firewall-packet-filters) from Red Hat
* Linode guide [on using firewalld](https://www.linode.com/docs/guides/introduction-to-firewalld-on-centos/)
## Brute-force protection
[fail2ban](https://www.fail2ban.org) and [SSHGuard](https://www.sshguard.net/) can be set up to monitor your log files for attempts to brute-force logins and other malicious behaviour. They can be configured to automatically insert firewall rules to block malicious IP addresses, either for a specific period of time or even indefinitely.
SSHGuard was initially designed just for SSH, but nowadays supports a variety of services. Fail2ban tends to support anything you can generate consistent log lines for, whereas SSHGuard's signature approach can catch more sophisticated or stealthy attacks as it computes an attack score over time.
Both SSHGuard and fail2ban ship with "backends" that can target iptables and nftables directly, or work with your frontend of choice like UFW or firewalld on Linux or pf on \*BSD. Make sure you review their documentation on how to correctly configure it.
* [ArchWiki](https://wiki.archlinux.org/title/Fail2ban) on fail2ban
* DigitalOcean guide on how to protect SSH with [fail2ban on Ubuntu](https://www.digitalocean.com/community/tutorial_collections/how-to-protect-ssh-with-fail2ban)
* Linode guide on how to [secure your server with fail2ban](https://www.linode.com/docs/guides/using-fail2ban-to-secure-your-server-a-tutorial/)
* [ArchWiki](https://wiki.archlinux.org/title/sshguard) on sshguard
* [FreeBSD manual](https://man.freebsd.org/cgi/man.cgi?query=sshguard&sektion=8&manpath=FreeBSD+13.2-RELEASE+and+Ports) for sshguard
* [SSHGuard setup](https://manpages.ubuntu.com/manpages/lunar/en/man7/sshguard-setup.7.html) manual for Ubuntu

View file

@ -0,0 +1,11 @@
# Enhanced security
These guides cover improving the security posture of your GoToSocial deployment. They don't involve tweaking settings in GoToSocial, but rather additional things you can do to better lock down your instance.
!!! note
Anything in these guides is meant to enhance the security of your GoToSocial deployment; they are not a replacement for good security practices like keeping your systems patched and up to date.
## Guides
* [Sandboxing the GoToSocial binary](sandboxing.md)
* [Firewall configuration](firewall.md)

View file

@ -0,0 +1,78 @@
# Application sandboxing
By sandboxing the GoToSocial binary it's possible to control which parts of the system GoToSocial can access, and limit which things it can read and write. This can be helpful to ensure that even in the face of a security issue in GoToSocial, an attacker is severely hindered in escalating their privileges and gaining a foothold on your system.
!!! note
As GoToSocial is still early in its development, the sandboxing policies we ship may get out of date. If you happen to run into this, please raise an issue on the issue tracker or better yet submit a PR to help us fix it.
Different distributions have different sandboxing mechanisms they prefer and support:
* **AppArmor** for the Debian or Ubuntu family of distributions or OpenSuSE, including when running with Docker
* **SELinux** for the Red Hat/Fedora/CentOS family of distributions or Gentoo
!!! warning "Containers and sandboxing"
Running GoToSocial as a container does not in and of itself provide much additional security. Despite their name, "containers do not contain". Containers are a distribution mechanism, not a security sandbox. To further secure your container you can instruct the container runtime to load the AppArmor profile and look into limiting which syscalls can be used using a seccomp profile.
## AppArmor
We ship an example AppArmor policy for GoToSocial, which you can retrieve and install as follows:
```sh
$ curl -LO 'https://github.com/superseriousbusiness/gotosocial/raw/main/example/apparmor/gotosocial'
$ sudo install -o root -g root gotosocial /etc/apparmor.d/gotosocial
$ sudo apparmor_parser -Kr /etc/apparmor.d/gotosocial
```
!!! tip
If you're using SQLite, the AppArmor profile expects the database in `/gotosocial/db/` so you'll need to adjust your configuration paths or the policy accordingly.
With the policy installed, you'll need to configure your system to use it to constrain the permissions GoToSocial has.
You can disable the policy like this:
```sh
$ sudo apparmor_parser -R /etc/apparmor.d/gotosocial
$ sudo rm -vi /etc/apparmor.d/gotosocial
```
Don't forget to roll back any configuration changes you made that load the AppArmor policy.
### systemd
Add the following to the systemd service, or create an override:
```ini
[Service]
...
AppArmorProfile=gotosocial
```
Reload systemd and restart GoToSocial:
```
$ systemctl daemon-reload
$ systemctl restart gotosocial
```
### Containers
!!! tip
You should review the [Docker](https://docs.docker.com/engine/security/apparmor/) or [Podman](https://docs.podman.io/en/latest/markdown/options/security-opt.html) documentation on AppArmor.
When using our example Compose file, you can tell it to load the AppArmor policy by tweaking it like so:
```yaml
services:
gotosocial:
...
security_opt:
- apparmor=gotosocial
```
When launching the container with `docker run` or `podman run`, you'll need the `--security-opt="apparmor=gotosocial"` command line flag.
## SELinux
!!! note
SELinux can only be used in combination with the [binary installation](../../getting_started/installation/metal.md) method. SELinux cannot be used to constrain GoToSocial when running in a container.
The SELinux policy is maintained by the community in the [`lzap/gotosocial-selinux`](https://github.com/lzap/gotosocial-selinux) repository on GitHub. Make sure to read its documentation, review the policy before using it and use their issue tracker for any support requests around the SELinux policy.

44
docs/advanced/tracing.md Normal file
View file

@ -0,0 +1,44 @@
# Tracing
GoToSocial comes with [OpenTelemetry][otel] based tracing built-in. It's not wired through every function, but our HTTP handlers and database library will create spans. How to configure tracing is explained in the [Observability configuration reference][obs].
In order to receive the traces, you need something to ingest them and then visualise them. There are many options available including self-hosted and commercial options.
We provide an example of how to do this using [Grafana Tempo][tempo] to ingest the spans and [Grafana][grafana] to explore them. Please beware that the configuration we provide is not suitable for a production setup. It can be used safely for local development and can provide a good starting point for setting up your own tracing infrastructure.
You'll need the files in [`example/tracing`][ext]. Once you have those you can run `docker-compose up -d` to get Tempo and Grafana running. With both services running, you can add the following to your GoToSocial configuration and restart your instance:
```yaml
tracing-enabled: true
tracing-transport: "grpc"
tracing-endpoint: "localhost:4317"
tracing-insecure: true
```
[otel]: https://opentelemetry.io/
[obs]: ../configuration/observability.md
[tempo]: https://grafana.com/oss/tempo/
[grafana]: https://grafana.com/oss/grafana/
[ext]: https://github.com/superseriousbusiness/gotosocial/tree/main/example/tracing
## Querying and visualising traces
Once you execute a few queries against your instance, you'll be able to find them in Grafana. You can use the Explore tab and pick Tempo as the datasource. Because our example configuration for Grafana enables [TraceQL][traceql], the Explore tab will have the TraceQL query type selected by default. You can switch to "Search" instead and find all traces emitted by GoToSocial under the "GoToSocial" service name.
Using TraceQL, a simple query to find all traces related to requests to `/api/v1/instance` would look like this:
```
{.http.route = "/api/v1/instance"}
```
If you wanted to see all GoToSocial traces, you could instead run:
```
{.service.name = "GoToSocial"}
```
Once you select a trace, a second panel will open up visualising the span. You can drill down from there, by clicking into every sub-span to see what it was doing.
![Grafana showing a trace for the /api/v1/instance endpoint](../assets/tracing.png)
[traceql]: https://grafana.com/docs/tempo/latest/traceql/

View file

@ -1,10 +1,16 @@
# Rate Limit
# Request Rate Limiting
To mitigate abuse + scraping of your instance, an IP-based HTTP rate limit is in place.
To mitigate abuse + scraping of your instance, IP-based HTTP rate limiting is in place.
This rate limit applies not just to the API, but to all requests (web, federation, etc).
There are separate rate limiters configured for different groupings of endpoints. In other words, being rate limited for one part of the API doesn't necessarily mean you will be rate limited for other parts. Each entry in the following list has a separate rate limiter:
By default, a maximum of 1000 requests in a 5 minute time window are allowed.
- `/users/*` and `/emoji/*` - ActivityPub (s2s) endpoints.
- `/auth/*` and `/oauth/*` - Sign in + OAUTH token requests.
- `/fileserver/*` - Media attachments, emojis, etc.
- `/nodeinfo/*` - NodeInfo endpoint(s).
- `/.well-known/*` - webfinger + nodeinfo requests.
By default, each rate limiter allows a maximum of 300 requests in a 5 minute time window: 1 request per second per client IP address.
Every response will include the current status of the rate limit with the following headers:

View file

@ -6,4 +6,4 @@ The resulting API documentation is rendered below, for quick reference.
If you'd like to do more with the spec, you can also view the [swagger.yaml](/api/swagger/swagger.yaml) directly, and then paste it into something like the [Swagger Editor](https://editor.swagger.io/) in order to autogenerate GoToSocial API clients in different languages, convert the doc to JSON or OpenAPI v3 specification, etc. See [here](https://swagger.io/tools/open-source/getting-started/) for more.
!!swagger swagger.yaml!!
<swagger-ui src="swagger.yaml"/>

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

35
docs/api/throttling.md Normal file
View file

@ -0,0 +1,35 @@
# Request Throttling
GoToSocial uses request throttling to limit the number of open connections to the API of your instance. This is designed to prevent your instance from accidentally being DDOS'd (aka [the hug of death](https://en.wikipedia.org/wiki/Slashdot_effect)) if a post gets boosted or replied to by an account with many thousands of followers.
Throttling means that only a limited number of HTTP requests to the API will be handled concurrently, in order to provide a snappy response to each request and move on quickly. The rationale is that it's better to handle fewer requests quickly, than to try to handle all incoming requests at once and take multiple seconds per request.
Throttling limits are applied across router groups, similar to the way that [rate limiting](./ratelimiting.md) is organized, so if one part of the API is currently being throttled, that doesn't mean they all are.
Throttling limits are calculated based on the number of CPUs available to GoToSocial, and the configuration value `advanced-throttling-multiplier`. The calculation is performed as follows:
- In-process queue limit = number of CPUs * CPU multiplier.
- Backlog queue limit = in-process queue limit * CPU multiplier.
This leads to the following values for the default multiplier (8):
```text
1 cpu = 08 in-process, 064 backlog
2 cpu = 16 in-process, 128 backlog
4 cpu = 32 in-process, 256 backlog
8 cpu = 64 in-process, 512 backlog
```
New requests that overflow the in-process limit are held in the backlog queue, and processed as soon as a spot is freed up (ie., when a currently in-process request is finished). Requests that cannot be processed, and cannot fit in the backlog queue will be responded to with http code [503 - Service Unavailable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503), and the `Retry-After` header will be set to `30` (seconds), to indicate that the caller should try again later.
Requests are not held in the backlog queue indefinitely: if requests in the backlog cannot be processed within 30 seconds of being received, they will also receive a code 503 and a 30s retry-after.
## Throttling FAQs
### Can I tune the request throttling?
Yes, just change the value of `advanced-throttling-multiplier` higher (if you have very powerful CPUs) or lower (if you have relatively less powerful CPUs).
### Can I disable the request throttling?
Yes. To do so, just set `advanced-throttling-multiplier` to `0` or less. This will disable HTTP request throttling entirely, and instead attempt to process all incoming requests at once. This is useful in cases where you want to do request throttling using an external service or a reverse-proxy, and you don't want GoToSocial to interfere with your setup.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View file

@ -0,0 +1,25 @@
[data-md-color-scheme="slate"] {
--md-primary-fg-color: #fd6a00;
--md-default-fg-color: #fafaff;
--md-default-fg-color--light: var(--md-default-fg-color);
--md-default-fg-color--lighter: var(--md-default-fg-color);
--md-default-fg-color--lightest: var(--md-default-fg-color);
--md-default-bg-color: #2a2b2f;
--md-default-bg-color--light: #35363b;
--md-default-bg-color--lighter: #3a3b41;
--md-default-bg-color--lightest: #4d4e56;
--md-typeset-color: var(--md-default-fg-color);
--md-typeset-a-color: #66befe;
--md-accent-fg-color: #89caff;
--md-footer-bg-color: var(--md-default-bg-color);
}
[data-md-color-scheme="slate"] .md-nav--primary .md-nav__title {
background: var(--md-default-bg-color) !important;
}
.md-content {
background: var(--md-default-bg-color--lightest);
}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 131 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 627 KiB

After

Width:  |  Height:  |  Size: 879 KiB

BIN
docs/assets/semaphore.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

BIN
docs/assets/tracing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 137 KiB

View file

@ -39,4 +39,11 @@ accounts-reason-required: true
# Options: [true, false]
# Default: false
accounts-allow-custom-css: false
# Int. If accounts-allow-custom-css is true, this is the permitted length in characters for
# CSS uploaded by accounts on this instance. No effect if accounts-allow-custom-css is false.
#
# Examples: [500, 5000, 9999]
# Default: 10000
accounts-custom-css-length: 10000
```

View file

@ -36,9 +36,8 @@ These are set to sensible defaults, so most server admins won't need to touch th
# Default: "lax"
advanced-cookies-samesite: "lax"
# Int. Amount of requests to permit from a single IP address within a span of 5 minutes.
# If this amount is exceeded, a 429 HTTP error code will be returned.
# See https://docs.gotosocial.org/en/latest/api/swagger/#rate-limit.
# Int. Amount of requests to permit per router grouping from a single IP address within
# a span of 5 minutes. If this amount is exceeded, a 429 HTTP error code will be returned.
#
# If you find yourself adjusting this limit because it's regularly being exceeded,
# you should first verify that your settings for `trusted-proxies` (above) are correct.
@ -50,6 +49,73 @@ advanced-cookies-samesite: "lax"
# If you set this to 0 or less, rate limiting will be disabled entirely.
#
# Examples: [1000, 500, 0]
# Default: 1000
advanced-rate-limit-requests: 1000
# Default: 300
advanced-rate-limit-requests: 300
# Int. Amount of open requests to permit per CPU, per router grouping, before applying http
# request throttling. Any requests beyond the calculated limit are held in a backlog queue for
# up to 30 seconds before either being processed or timing out. Requests that don't fit in the backlog
# queue will have status 503 returned to them, and the header 'Retry-After' will be set to 30 seconds.
#
# Open request limit is available CPUs * multiplier; backlog queue limit is limit * multiplier.
#
# Example values for multiplier 8:
#
# 1 cpu = 08 open, 064 backlog
# 2 cpu = 16 open, 128 backlog
# 4 cpu = 32 open, 256 backlog
#
# Example values for multiplier 4:
#
# 1 cpu = 04 open, 016 backlog
# 2 cpu = 08 open, 032 backlog
# 4 cpu = 16 open, 064 backlog
#
# A multiplier of 8 is a sensible default, but you may wish to increase this for instances
# running on very performant hardware, or decrease it for instances using v. slow CPUs.
#
# If you set this to 0 or less, http request throttling will be disabled entirely.
#
# Examples: [8, 4, 9, 0]
# Default: 8
advanced-throttling-multiplier: 8
# Duration. Time period to use as the "retry-after" header value in response to throttled requests.
# Minimum resolution is 1 second.
#
# Examples: [30s, 10s, 5s, 1m]
# Default: "30s"
advanced-throttling-retry-after: "30s"
# Int. CPU multiplier for the amount of goroutines to spawn in order to send messages via ActivityPub.
# Messages will be batched so that at most multiplier * CPU count messages will be sent out at once.
# This can be tuned to limit concurrent POSTing to remote inboxes, preventing your instance CPU
# usage from skyrocketing when an account with many followers posts a new status.
#
# Messages are split among available senders, and each sender processes its assigned messages in serial.
# For example, say a user with 1000 followers is on an instance with 2 CPUs. With the default multiplier
# of 2, this means 4 senders would be in process at once on this instance. When the user creates a new post,
# each sender would end up iterating through about 250 Create messages + delivering them to remote instances.
#
# If you set this to 0 or less, only 1 sender will be used regardless of CPU count. This may be
# useful in cases where you are working with very tight network or CPU constraints.
#
# Example values for multiplier 2 (default):
#
# 1 cpu = 2 concurrent senders
# 2 cpu = 4 concurrent senders
# 4 cpu = 8 concurrent senders
#
# Example values for multiplier 4:
#
# 1 cpu = 4 concurrent senders
# 2 cpu = 8 concurrent senders
# 4 cpu = 16 concurrent senders
#
# Example values for multiplier <1:
#
# 1 cpu = 1 concurrent sender
# 2 cpu = 1 concurrent sender
# 4 cpu = 1 concurrent sender
advanced-sender-multiplier: 2
```

View file

@ -107,4 +107,64 @@ db-tls-mode: "disable"
# Examples: ["/path/to/some/cert.crt"]
# Default: ""
db-tls-ca-cert: ""
# Int. Number to multiply by CPU count to set permitted total of open database connections (in-use and idle).
# You can use this setting to tune your database connection behavior, though most admins won't need to touch it.
#
# Example values for multiplier 8:
#
# 1 cpu = 08 open connections
# 2 cpu = 16 open connections
# 4 cpu = 32 open connections
#
# Example values for multiplier 4:
#
# 1 cpu = 04 open connections
# 2 cpu = 08 open connections
# 4 cpu = 16 open connections
#
# A multiplier of 8 is a sensible default, but you may wish to increase this for instances
# running on very performant hardware, or decrease it for instances using v. slow CPUs.
#
# If you set the multiplier to less than 1, only one open connection will be used regardless of cpu count.
#
# PLEASE NOTE!!: This setting currently only applies for Postgres. SQLite will always use 1 connection regardless
# of what is set here. This behavior will change in future when we implement better SQLITE_BUSY handling.
# See https://github.com/superseriousbusiness/gotosocial/issues/1407 for more details.
#
# Examples: [16, 8, 10, 2]
# Default: 8
db-max-open-conns-multiplier: 8
# String. SQLite journaling mode.
# SQLite only -- unused otherwise.
# If set to empty string, the sqlite default will be used.
# See: https://www.sqlite.org/pragma.html#pragma_journal_mode
# Examples: ["DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"]
# Default: "WAL"
db-sqlite-journal-mode: "WAL"
# String. SQLite synchronous mode.
# SQLite only -- unused otherwise.
# If set to empty string, the sqlite default will be used.
# See: https://www.sqlite.org/pragma.html#pragma_synchronous
# Examples: ["OFF", "NORMAL", "FULL", "EXTRA"]
# Default: "NORMAL"
db-sqlite-synchronous: "NORMAL"
# Byte size. SQlite cache size.
# SQLite only -- unused otherwise.
# If set to empty string or zero, the sqlite default (2MiB) will be used.
# See: https://www.sqlite.org/pragma.html#pragma_cache_size
# Examples: ["0", "2MiB", "8MiB", "64MiB"]
# Default: "8MiB"
db-sqlite-cache-size: "8MiB"
# Duration. SQlite busy timeout.
# SQLite only -- unused otherwise.
# If set to empty string or zero, the sqlite default will be used.
# See: https://www.sqlite.org/pragma.html#pragma_busy_timeout
# Examples: ["0s", "1s", "30s", "1m", "5m"]
# Default: "30m"
db-sqlite-busy-timeout: "30m"
```

View file

@ -23,11 +23,21 @@ log-level: "info"
# Default: false
log-db-queries: false
# Bool. Include the client IP in the emitted log lines
# Options: [true, false]
# Default: true
log-client-ip: true
# String. Application name to use internally.
# Examples: ["My Application","gotosocial"]
# Default: "gotosocial"
application-name: "gotosocial"
# String. The user that will be shown instead of the landing page. if no user is set, the landing page will be shown.
# Examples: "admin"
# Default: ""
landing-page-user: ""
# String. Hostname that this server will be reachable at. Defaults to localhost for local testing,
# but you should *definitely* change this when running for real, or your server won't work at all.
# DO NOT change this after your server has already run once, or you will break things!
@ -43,6 +53,11 @@ host: "localhost"
# to "gts.example.org/.well-known/webfinger" so that GtS can handle them properly.
#
# You should also redirect requests at "example.org/.well-known/nodeinfo" in the same way.
#
# You should also redirect requests at "example.org/.well-known/host-meta" in the same way. This endpoint
# is used by a number of clients to discover the API endpoint to use when the host and account domain are
# different.
#
# An empty string (ie., not set) means that the same value as 'host' will be used.
#
# DO NOT change this after your server has already run once, or you will break things!
@ -64,9 +79,11 @@ protocol: "https"
# String. Address to bind the GoToSocial server to.
# This can be an IPv4 address or an IPv6 address (surrounded in square brackets), or a hostname.
# Default value will bind to all interfaces.
# You probably won't need to change this unless you're setting GoToSocial up in some fancy way or
# you have specific networking requirements.
# The default value will bind to all interfaces, which makes the server
# accessible by other machines. For most setups there is no need to change this.
# If you are using GoToSocial in a reverse proxy setup with the proxy running on
# the same machine, you will want to set this to "localhost" or an equivalent,
# so that the proxy can't be bypassed.
# Examples: ["0.0.0.0", "172.128.0.16", "localhost", "[::]", "[2001:db8::fed1]"]
# Default: "0.0.0.0"
bind-address: "0.0.0.0"

View file

@ -0,0 +1,68 @@
# HTTP Client
## Settings
```yaml
################################
##### HTTP CLIENT SETTINGS #####
################################
# Settings for OUTGOING http client connections used by GoToSocial to make
# requests to remote resources (status GETs, media GETs, inbox POSTs, etc).
http-client:
# Duration. Timeout to use for outgoing HTTP requests. If the timeout
# is exceeded, the connection to the remote server will be dropped.
# A value of 0s indicates no timeout: this is not advised!
# Examples: ["5s", "10s", "0s"]
# Default: "10s"
timeout: "10s"
########################################
#### RESERVED IP RANGE EXCEPTIONS ######
########################################
#
# Explicitly allow or block outgoing dialing within the provided IPv4/v6 CIDR ranges.
#
# By default, as a basic security precaution, GoToSocial blocks outgoing dialing within most "special-purpose"
# IP ranges. However, it may be desirable for admins with more exotic setups (proxies, funky NAT, etc) to
# explicitly override one or more of these otherwise blocked ranges.
#
# Each of the below allow/block config options accepts an array of IPv4 and/or IPv6 CIDR strings.
# For example, to override the hardcoded block of IPv4 and IPv6 dialing to localhost, set:
#
# allow-ips: ["127.0.0.1/32", "::1/128"].
#
# You can also use YAML multi-line arrays to define these, but be diligent with indentation.
#
# When dialing, GoToSocial will first check if the destination falls within explicitly allowed IP ranges,
# then explicitly blocked IP ranges, then the default (hardcoded) blocked IP ranges, returning OK on the
# first allowed match, not OK on the first blocked match, or just defaulting to OK if nothing is matched.
#
# As with all security settings, it is better to start too restrictive and then ease off depending on
# your use case, than to start too permissive and try to close the stable door after the horse has
# already bolted. With this in mind:
# - Don't touch these settings unless you have a good reason to, and only if you know what you're doing.
# - When adding explicitly allowed exceptions, use the narrowest possible CIDR for your use case.
#
# For reserved / special ranges, see:
# - https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
# - https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
#
# Both allow-ips and block-ips default to an empty array.
allow-ips: []
block-ips: []
# Bool. Disable verification of TLS certificates of remote servers.
# With this set to 'true', GoToSocial will not error when a remote
# server presents an invalid or self-signed certificate.
#
# THIS SETTING SHOULD BE USED FOR TESTING ONLY! IF YOU TURN THIS
# ON WHILE RUNNING IN PRODUCTION YOU ARE LEAVING YOUR SERVER WIDE
# OPEN TO MAN IN THE MIDDLE ATTACKS! DO NOT CHANGE THIS SETTING
# UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING AND WHY YOU'RE DOING IT.
#
# Default: false
tls-insecure-skip-verify: false
```

View file

@ -24,6 +24,12 @@ instance-expose-peers: false
# Default: false
instance-expose-suspended: false
# Bool. Allow unauthenticated users to view /about/suspended,
# showing the HTML rendered list of instances that this instance blocks/suspends.
# Options: [true, false]
# Default: false
instance-expose-suspended-web: false
# Bool. Allow unauthenticated users to make queries to /api/v1/timelines/public in order
# to see a list of public posts on this server. Even if set to 'false', then authenticated
# users (members of the instance) will still be able to query the endpoint.

View file

@ -1,42 +0,0 @@
# LetsEncrypt
## Settings
```yaml
##############################
##### LETSENCRYPT CONFIG #####
##############################
# Config pertaining to the automatic acquisition and use of LetsEncrypt HTTPS certificates.
# Bool. Whether or not letsencrypt should be enabled for the server.
# If false, the rest of the settings here will be ignored.
# If you serve GoToSocial behind a reverse proxy like nginx or traefik, leave this turned off.
# If you don't, then turn it on so that you can use https.
# Options: [true, false]
# Default: false
letsencrypt-enabled: false
# Int. Port to listen for letsencrypt certificate challenges on.
# If letsencrypt is enabled, this port must be reachable or you won't be able to obtain certs.
# If letsencrypt is disabled, this port will not be used.
# This *must not* be the same as the webserver/API port specified above.
# Examples: [80, 8000, 1312]
# Default: 80
letsencrypt-port: 80
# String. Directory in which to store LetsEncrypt certificates.
# It is a good move to make this a sub-path within your storage directory, as it makes
# backup easier, but you might wish to move them elsewhere if they're also accessed by other services.
# In any case, make sure GoToSocial has permissions to write to / read from this directory.
# Examples: ["/home/gotosocial/storage/certs", "/acmecerts"]
# Default: "/gotosocial/storage/certs"
letsencrypt-cert-dir: "/gotosocial/storage/certs"
# String. Email address to use when registering LetsEncrypt certs.
# Most likely, this will be the email address of the instance administrator.
# LetsEncrypt will send notifications about expiring certificates etc to this address.
# Examples: ["admin@example.org"]
# Default: ""
letsencrypt-email-address: ""
```

View file

@ -7,7 +7,7 @@
##### MEDIA CONFIG #####
########################
# Config pertaining to user media uploads (videos, image, image descriptions).
# Config pertaining to media uploads (videos, image, image descriptions, emoji).
# Int. Maximum allowed image upload size in bytes.
# Examples: [2097152, 10485760]
@ -37,8 +37,8 @@ media-description-max-chars: 500
#
# If this is set to 0, then media from remote instances will be cached indefinitely.
# Examples: [30, 60, 7, 0]
# Default: 30
media-remote-cache-days: 30
# Default: 7
media-remote-cache-days: 7
# Int. Max size in bytes of emojis uploaded to this instance via the admin API.
# The default is the same as the Mastodon size limit for emojis (50kb), which allows
@ -53,6 +53,6 @@ media-emoji-local-max-size: 51200
# This strikes a good balance between decent interoperability with instances that have
# higher emoji size limits, and not taking up too much space in storage.
# Examples: [51200, 102400]
# Default: 51200
# Default: 102400
media-emoji-remote-max-size: 102400
```

View file

@ -0,0 +1,38 @@
# Observability
These settings let you tune and configure certain observability related behaviours.
## Settings
```yaml
##################################
##### OBSERVABILITY SETTINGS #####
##################################
# String. Header name to use to extract a request or trace ID from. Typically set by a
# loadbalancer or proxy.
# Default: "X-Request-Id"
request-id-header: "X-Request-Id"
# Bool. Enable OpenTelemetry based tracing support.
# Default: false
tracing-enabled: false
# String. Set the transport protocol for the tracing system. Can either be "grpc" for
# OTLP gRPC or "jaeger" for jaeger based ingesters.
# Options: ["grpc", "jaeger"]
# Default: "grpc"
tracing-transport: "grpc"
# String. Endpoint of the trace ingester. When using the gRPC based transport, the
# endpoint is usually a single address/port combination. For the jaeger transport it
# should be a fully qualified URL.
# OTLP gRPC or "jaeger" for jaeger based ingesters
# Examples: ["localhost:4317", "http://localhost:14268/api/traces"]
# Default: ""
tracing-endpoint: ""
# Bool. Disable HTTPS for the gRPC transport protocol.
# Default: false
tracing-insecure-transport: false
```

View file

@ -10,6 +10,9 @@ This is very convenient in the following cases:
- You want to delegate management of users, accounts, passwords etc. to an external service to make admin easier for yourself.
- You already have a lot of users in an external system and you don't want to have to recreate them all in GoToSocial manually.
!!! tip
If a user doesn't exist yet, login will fail if your IdP doesn't return a non-empty `email` as part of the claims. The email needs to be unique on this instance. Though we use the `sub` claim to associate the external identity with a GtS user, when a user is created it needs an email associated with it.
## Settings
GoToSocial exposes the following configuration settings for OIDC, shown below with their default values.
@ -60,7 +63,7 @@ oidc-client-secret: ""
# Array of string. Scopes to request from the OIDC provider. The returned values will be used to
# populate users created in GtS as a result of the authentication flow. 'openid' and 'email' are required.
# 'profile' is used to extract a username for the newly created user.
# 'groups' is optional and can be used to determine if a user is an admin (if they're in the group 'admin' or 'admins').
# 'groups' is optional and can be used to determine if a user is an admin based on oidc-admin-groups.
# Examples: See eg., https://auth0.com/docs/scopes/openid-connect-scopes
# Default: ["openid", "email", "profile", "groups"]
oidc-scopes:
@ -68,6 +71,18 @@ oidc-scopes:
- "email"
- "profile"
- "groups"
# Bool. Link OIDC authenticated users to existing ones based on their email address.
# This is mostly intended for migration purposes if you were running previous versions of GTS
# which only correlated users with their email address. Should be set to false for most usecases.
# Options: [true, false]
# Default: false
oidc-link-existing: false
# Array of string. If the returned ID token contains a 'groups' claim that matches one of the
# groups in oidc-admin-groups, then this user will be granted admin rights on the GtS instance
# Default: []
oidc-admin-groups: []
```
## Behavior
@ -76,47 +91,35 @@ When OIDC is enabled on GoToSocial, the default sign-in page redirects automatic
This means that OIDC essentially *replaces* the normal GtS email/password sign-in flow.
When a user logs in through OIDC, GoToSocial will request that user's preferred email address and username from the OIDC provider. It will then use the returned email address to either:
Due to the way the ActivityPub standard works, you _cannot_ change your username
after it has been set. This conflicts with the OIDC spec which does not
guarantee that the `preferred_username` field is stable.
*If the email address is already associated with a user/account*: sign the requester in as that user/account.
To work with this, we ask the user to provide a username on their first login
attempt. The field for this is pre-filled with the value of the `preferred_username` claim.
Or:
After authenticating, GtS stores the `sub` claim supplied by the OIDC provider.
On subsequent authentication attempts, the user is looked up using this claim
exclusively.
*If the email address is not yet associated with a user/account*: create a new user and account with the returned credentials, and sign the requester in as that user/account.
In other words, GoToSocial completely delegates sign-in authority to the OIDC provider, and trusts whatever credentials it returns.
### Username conflicts
In some cases, such as when a server has been switched to use OIDC after already using default settings for a while, there may be an overlap between usernames returned from OIDC, and usernames that already existed in the database.
For example, let's say that someone with username `gordonbrownfan` and email address `gordon_is_best@example.org` has an account on a GtS instance that uses the default sign-in flow.
That GtS instance then switches to using OIDC login. However, in the OIDC's storage there's also a user with username `gordonbrownfan`. If this user has the email address `gordon_is_best@example.org`, then GoToSocial will assume that the two users are the same and just log `gordonbrownfan` in as though nothing had changed. No problem!
However, if the user in the OIDC storage has a different email address, GoToSocial will try to create a new user and account for this person.
Since the username `gordonbrownfan` is already taken, GoToSocial will try `gordonbrownfan1`. If this is also taken, it will try `gordonbrownfan2`, and so on, until it finds a username that's not yet taken. It will then sign the requester in as that user/account, distinct from the original `gordonbrownfan`.
### Malformed usernames
A username returned from an OIDC provider might not always fit the pattern of what GoToSocial accepts as a valid username, ie., lower-case letters, numbers, and underscores. In this case, GoToSocial will do its best to parse the returned username into something that fits the pattern.
For example, say that an OIDC provider returns the username `Marx Is Great` for a sign in, which doesn't fit the pattern because it contains upper-case letters and spaces.
In this case, GtS will convert it into `marx_is_great` by applying the following rules:
1. Trim any leading or trailing whitespace.
2. Convert all letters to lowercase.
3. Replace spaces with underscores.
Unfortunately, at this point GoToSocial doesn't know how to handle returned usernames containing special characters such as `@` or `%`, so these will return an error.
This then allows you to change the username on a provider level without losing
access to your GtS account.
### Group membership
Most OIDC providers allow for the concept of groups and group memberships in returned claims. GoToSocial can use group membership to determine whether or not a user returned from an OIDC flow should be created as an admin account or not.
If the returned OIDC groups information for a user contains membership of the groups `admin` or `admins`, then that user will be created/signed in as though they are an admin.
If the returned OIDC groups information for a user contains membership of the groups configured in `oidc-admin-groups`, then that user will be created/signed in as though they are an admin.
## Migrating from old versions
If you're moving from an old version of GtS which used the unstable `email`
claim for unique user identification, you can set the `oidc-link-existing`
configuration to `true`. If no user can be found for the ID returned by the
provider, a lookup based on the `email` claim is performed instead. If this
succeeds, the stable id is added to the database for the matching user.
You should only use this for a limited time to avoid malicious account takeover.
## Provider Examples

View file

@ -45,6 +45,18 @@ smtp-password: ""
# Examples: ["mail@example.org"]
# Default: ""
smtp-from: ""
# Bool. If true, when an email is sent that has multiple recipients, each recipient
# will be included in the To field, so that each recipient can see who else got the
# email, and they can 'reply all' to the other recipients if they want to.
#
# If false, email will be sent to Undisclosed Recipients, and each recipient will not
# be able to see who else received the email.
#
# It might be useful to change this setting to 'true' if you want to be able to discuss
# new moderation reports with other admins by 'replying-all' to the notification email.
# Default: false
smtp-disclose-recipients: false
```
Note that if you don't set `Host`, then email sending via smtp will be disabled, and the other settings will be ignored. GoToSocial will still log (at trace level) emails that *would* have been sent if smtp was enabled.
@ -59,11 +71,19 @@ The exception to this requirement is if you're running your mail server (or brid
### When are emails sent?
Currently, emails are only sent to users to request email confirmation when a new account is created, or to serve password reset requests. More email functionality will probably be added later.
Currently, emails are sent:
- To the provided email address of a new user to request email confirmation when a new account is created via the API.
- To all active instance moderators + admins when a new moderation report is received. By default, recipients are Bcc'd, but you can change this behavior with the setting `smtp-disclose-recipients`.
- To the creator of a report (on this instance) when the report is closed by a moderator.
### Can I test if my SMTP configuration is correct?
Yes, you can use the API to send a test email to yourself. Check the API documentation for the `/api/v1/admin/email/test` endpoint.
### HTML versus Plaintext
Emails are sent in HTML by default. At this point, there is no option to send emails in plaintext, but this is something that might be added later if there's enough demand for it.
Emails are sent in plaintext by default. At this point, there is no option to send emails in html, but this is something that might be added later if there's enough demand for it.
## Customization

View file

@ -24,11 +24,9 @@ storage-local-base-path: "/gotosocial/storage"
# String. API endpoint of the S3 compatible service.
# Only required when running with the s3 storage backend.
#
# If your endpoint contains the bucket name, all files will be put into a
# subdirectory with the name of `storage-s3-bucket`
#
# Examples: ["minio:9000", "s3.nl-ams.scw.cloud", "s3.us-west-002.backblazeb2.com"]
# GoToSocial uses "DNS-style" when accessing buckets.
# If you are using Scaleways object storage, please remove the "bucket name" from the endpoint address
# Default: ""
storage-s3-endpoint: ""
@ -37,18 +35,27 @@ storage-s3-endpoint: ""
# Default: false
storage-s3-proxy: false
# Bool. Use SSL for S3 connections.
#
# Only set this to 'false' when testing locally.
#
# Default: true
storage-s3-use-ssl: true
# String. Access key part of the S3 credentials.
# Consider setting this value using environment variables to avoid leaking it via the config file
# Only required when running with the s3 storage backend.
# Examples: ["AKIAJSIE27KKMHXI3BJQ","miniouser"]
# Default: ""
storage-s3-access-key: ""
# String. Secret key part of the S3 credentials.
# Consider setting this value using environment variables to avoid leaking it via the config file
# Only required when running with the s3 storage backend.
# Examples: ["5bEYu26084qjSFyclM/f2pz4gviSfoOg+mFwBH39","miniopassword"]
# Default: ""
storage-s3-secret-key: ""
# String. Name of the storage bucket.
#
# If you have already encoded your bucket name in the storage-s3-endpoint, this
@ -62,6 +69,62 @@ storage-s3-secret-key: ""
storage-s3-bucket: ""
```
### AWS S3 Bucket Configuration
#### Bucket Created
GoToSocial by default creates signed URL's which means we dont need to change anything major on the policies of the bucket.
Here are the steps to follow for bucket creation
1. Login to AWS -> select S3 as service.
2. click Create Bucket
3. Provide a unique name and avoid adding "." in the name
4. Do not change the public access settings (Let them be on "block public access" mode)
#### AWS ACCESS KEY Configuration
1. In AWS Console -> IAM (under Security, Identity, & Compliance)
2. Add a user with programatic api's access
3. We recommend setting up below listed policy, replace <bucketname> with your buckets name
```json
{
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<bucket_name>",
"arn:aws:s3:::<bucket_name>/*"
]
}
]
}
```
4. Provide the values in config above
* storage-s3-endpoint -> should be your bucket location say `s3.ap-southeast-1.amazonaws.com`
* storage-s3-access-key -> Access key you obtained for the user created above
* storage-s3-secret-key -> Secret key you obtained for the user created above
* storage-s3-bucket -> Keep this as the <bucketname> that you created just now.
#### Migrating data from local storage to AWS s3 bucket
This step is only needed if you have a running instance. Ignore this if you are setting up a fresh instance.
We have provided [s3cmd](https://github.com/s3tools/s3cmd) command for the copy operation.
```bash
s3cmd sync --add-header="Cache-Control:public, max-age=315576000, immutable" ./ s3://<bucket name>
```
### Migrating between backends
Currently, migration between backends is freely possible. To do so, you only

View file

@ -32,7 +32,7 @@ syslog-enabled: false
# String. Protocol to use when directing logs to syslog. Leave empty to connect to local syslog.
# Options: ["udp", "tcp", ""]
# Default: "tcp"
# Default: "udp"
syslog-protocol: "udp"
# String. Address:port to send syslog logs to. Leave empty to connect to local syslog.

66
docs/configuration/tls.md Normal file
View file

@ -0,0 +1,66 @@
# TLS
It's possible to configure TLS support in one of two ways:
* Built-in support for Lets Encrypt / ACME compatible vendors
* Loading TLS files from disk
It is not possible to have both methods enabled at the same time.
Note that when using TLS files loaded from disk you are responsible for restarting the instance when the files change. They are not automatically reloaded.
## Settings
```yaml
##############################
##### LETSENCRYPT CONFIG #####
##############################
# Config pertaining to the automatic acquisition and use of LetsEncrypt HTTPS certificates.
# Bool. Whether or not letsencrypt should be enabled for the server.
# If false, the rest of the settings here will be ignored.
# If you serve GoToSocial behind a reverse proxy like nginx or traefik, leave this turned off.
# If you don't, then turn it on so that you can use https.
# Options: [true, false]
# Default: false
letsencrypt-enabled: false
# Int. Port to listen for letsencrypt certificate challenges on.
# If letsencrypt is enabled, this port must be reachable or you won't be able to obtain certs.
# If letsencrypt is disabled, this port will not be used.
# This *must not* be the same as the webserver/API port specified above.
# Examples: [80, 8000, 1312]
# Default: 80
letsencrypt-port: 80
# String. Directory in which to store LetsEncrypt certificates.
# It is a good move to make this a sub-path within your storage directory, as it makes
# backup easier, but you might wish to move them elsewhere if they're also accessed by other services.
# In any case, make sure GoToSocial has permissions to write to / read from this directory.
# Examples: ["/home/gotosocial/storage/certs", "/acmecerts"]
# Default: "/gotosocial/storage/certs"
letsencrypt-cert-dir: "/gotosocial/storage/certs"
# String. Email address to use when registering LetsEncrypt certs.
# Most likely, this will be the email address of the instance administrator.
# LetsEncrypt will send notifications about expiring certificates etc to this address.
# Examples: ["admin@example.org"]
# Default: ""
letsencrypt-email-address: ""
##############################
##### MANUAL TLS CONFIG #####
##############################
# String. Path to a PEM-encoded file on disk that includes the certificate chain
# and the public key
# Examples: ["/gotosocial/storage/certs/chain.pem"]
# Default: ""
tls-certificate-chain: ""
# String. Path to a PEM-encoded file on disk containing the private key for the
# associated tls-certificate-chain
# Examples: ["/gotosocial/storage/certs/private.pem"]
# Default: ""
tls-certificate-key: ""
```

View file

@ -1,45 +1,14 @@
name: gotosocial-docs
channels:
- defaults
- conda-forge
- nodefaults
dependencies:
- _libgcc_mutex=0.1=main
- _openmp_mutex=4.5=1_gnu
- bzip2=1.0.8=h7b6447c_0
- ca-certificates=2021.10.26=h06a4308_2
- certifi=2020.6.20=pyhd3eb1b0_3
- ld_impl_linux-64=2.35.1=h7274673_9
- libffi=3.3=he6710b0_2
- libgcc-ng=9.3.0=h5101ec6_17
- libgomp=9.3.0=h5101ec6_17
- libstdcxx-ng=9.3.0=hd4cf53a_17
- libuuid=1.0.3=h7f8727e_2
- ncurses=6.3=h7f8727e_2
- openssl=1.1.1l=h7f8727e_0
- python=3.10.0=h151d27f_3
- readline=8.1=h27cfd23_0
- sqlite=3.36.0=hc218d9a_0
- tk=8.6.11=h1ccaba5_0
- tzdata=2021e=hda174b7_0
- wheel=0.37.0=pyhd3eb1b0_1
- xz=5.2.5=h7b6447c_0
- zlib=1.2.11=h7b6447c_3
- python=3.11.3=h2755cc3_0_cpython
- pip=23.1.2=pyhd8ed1ab_0
- mkdocs=1.4.3=pyhd8ed1ab_0
- mkdocs-material=9.1.9=pyhd8ed1ab_0
- mkdocs-material-extensions=1.1.1=pyhd8ed1ab_0
- pillow=9.5.0=py311h573f0d3_0
- cairosvg=2.6.0=pyhd8ed1ab_0
- pip:
- click==8.0.3
- ghp-import==2.0.2
- importlib-metadata==4.8.2
- jinja2==3.0.3
- markdown==3.3.4
- markupsafe==2.0.1
- mergedeep==1.3.4
- mkdocs==1.2.3
- mkdocs-render-swagger-plugin==0.0.3
- packaging==21.2
- pip==21.2.4
- pyparsing==2.4.7
- python-dateutil==2.8.2
- pyyaml==6.0
- pyyaml-env-tag==0.1
- setuptools==58.0.4
- six==1.16.0
- watchdog==2.1.6
- zipp==3.6.0
- mkdocs-swagger-ui-tag==0.6.1

View file

@ -1,30 +1,50 @@
# Frequently Asked Questions
- **Where's the user interface?** GoToSocial is just a bare server for the most part and is designed to be used thru external applications. [Pinafore](https://pinafore.social) and [Tusky](https://tusky.app/) are the best-supported, but anything that supports the Mastodon API should work, other than the features GoToSocial doesn't yet have. Permalinks and profile pages are served directly thru GoToSocial as well as the admin panel, but most interaction goes thru the apps.
## Where's the user interface?
- **What happened to the gifs?** While GoToSocial supports gifs, it doesn't support videos. This wouldn't be a big problem, except that Mastodon doesn't support gifs; it converts them into videos when they get uploaded. So if someone posts a gif from a Mastodon server, it won't be visible. At the time of this writing, the video will be dropped altogether, but [in the future there should be at least a placeholder link](https://github.com/superseriousbusiness/gotosocial/issues/765).
GoToSocial is just a bare server for the most part and is designed to be used thru external applications. [Semaphore](https://semaphore.social/) and [Tusky](https://tusky.app/) are the best-supported, but anything that supports the Mastodon API should work, other than the features GoToSocial doesn't yet have. Permalinks and profile pages are served directly through GoToSocial as well as the settings panel, but most interaction goes through the apps.
- **Why aren't my posts showing up on my profile page?** Unlike Mastodon, the default post visibility is Unlisted. If you want something to be visible on your profile page, the post must have Public visibility.
## Why aren't my posts showing up on my profile page?
- **Why aren't my posts showing up on other servers?** First check the visibility as noted above. TODO: explain how to debug common federation issues
Unlike Mastodon, the default post visibility is Unlisted. If you want something to be visible on your profile page, the post must have Public visibility.
- **Why am I getting frequent error responses?** GoToSocial is configured to use per-IP [rate limiting](https://docs.gotosocial.org/en/latest/api/ratelimiting/) by default, but in certain situations it can't accurately identify the remote IP and will treat all connections as coming from the same place. In those cases, the rate limiting needs to be disabled or reconfigured.
## Why aren't my posts showing up on other servers?
- **My instance is deployed and I'm logged in to a client but my timelines are empty, what's up there?** To see posts, you have to start following people! Once you've followed a few people and they've posted or boosted things, you'll start seeing them in your timelines. Right now GoToSocial doesn't have a way of 'backfilling' posts -- that is, fetching previous posts from other instances -- so you'll only see new posts of people you follow. If you want to interact with an older post of theirs, you can copy the link to the post from their web profile, and paste it in to your client's search bar.
First check the visibility as noted above. TODO: explain how to debug common federation issues
- **How can I sign up for a server?** Right now the only way to create an account is by the server's admin to run a command directly on the server. A web-based signup flow is in the roadmap but not implemented yet.
## Why am I getting frequent http 429 error responses?
- **Why's it still in alpha?** Take a look at the [list of open bugs](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and the [roadmap](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md) for a more detailed rundown, but the main missing features at the time of this writing are:
* videos
* reporting posts to admins
* muting conversations
* backfill of posts
* web-based signup
* profile metadata fields
* lists of users
* pinning posts to your profile
* polls
* scheduling posts
* account migration
* federated hashtag search
* shared block lists across servers
GoToSocial is configured to use per-IP [rate limiting](./api/ratelimiting.md) by default, but in certain situations it can't accurately identify the remote IP and will treat all connections as coming from the same place. In those cases, the rate limiting needs to be disabled or reconfigured.
## Why am I getting frequent HTTP 503 error responses?
Code 503 is returned to callers when your instance is under heavy load and requests are being throttled. This behavior can be tuned as desired, or turned off entirely, see [here](./api/throttling.md).
## I keep getting a 400 Bad Request error, and I have done everything suggested by the error message. What should I do?
Verify that the `host` configuration matches the domain that GoToSocial is served from (the domain that users use to acces the server).
## I keep seeing 'dial within blocked / reserved IP range' in my server logs, and I can't connect to some instances from my instance, what do I do?
The IP address of the remote instance may be in one of the blocked "special use" IP ranges hardcoded into GoToSocial for security reasons. If you need to, you can override this in your configuration file. Have a look at the [http client docs](./configuration/httpclient.md) for this, and please read the warnings there carefully! If you add an explicit allow, you will have to restart your GoToSocial instance to make the config take effect.
## My instance is deployed and I'm logged in to a client but my timelines are empty, what's up there?
To see posts, you have to start following people! Once you've followed a few people and they've posted or boosted things, you'll start seeing them in your timelines. Right now GoToSocial doesn't have a way of 'backfilling' posts -- that is, fetching previous posts from other instances -- so you'll only see new posts of people you follow. If you want to interact with an older post of theirs, you can copy the link to the post from their web profile, and paste it in to your client's search bar.
## How can I sign up for a server?
Right now the only way to create an account is by the server's admin to run a command directly on the server. A web-based signup flow is in the roadmap but not implemented yet.
## Why's it still in alpha?
Take a look at the [list of open bugs](https://github.com/superseriousbusiness/gotosocial/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and the [roadmap](https://github.com/superseriousbusiness/gotosocial/blob/main/ROADMAP.md) for a more detailed rundown, but the main missing features at the time of this writing are:
- muting conversations
- backfill of posts
- web-based signup
- polls
- scheduling posts
- account migration
- federated hashtag search
- shared block lists across servers

View file

@ -1,45 +0,0 @@
# Conversation Threads
Due to the nature of decentralization and federation, it is practically impossible for any one server on the fediverse to be aware of every post in a given conversation thread.
With that said, it is possible to do 'best effort' dereferencing of threads, whereby remote replies are fetched from one server onto another, to try to more fully flesh out a conversation.
GoToSocial does this by iterating up and down the thread of a conversation, pulling in remote statuses where possible.
## Example
Let's say we have two accounts: `local_account` on `our.server`, and `remote_1` on `remote.1`.
In this scenario, `local_account` follows `remote_1`, so posts from `remote_1` show up in the home timeline of `local_account`.
Now, `remote_1` boosts/reblogs a post from a third account, `remote_2`, residing on server `remote.2`.
`local_account` does not follow `remote_2`, and neither does anybody else on `our.server`, which means that `our.server` has not seen this post by `remote_2` before.
![A diagram of the conversation thread, showing the post from remote_2, and possible ancestor and descendant posts](../../assets/diagrams/conversation_thread.png)
What GoToSocial will do now, is 'dereference' the post by `remote_2` to check if it is part of a thread and, if so, whether any other parts of the thread can be obtained.
GtS begins by checking the `inReplyTo` property of the post, which is set when a post is a reply to another post. [See here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto). If `inReplyTo` is set, GoToSocial derefences the replied-to post. If *this* post also has an `inReplyTo` set, then GoToSocial dereferences that too, and so on.
Once all of these **ancestors** of a status have been retrieved, GtS will begin working down through the **descendants** of posts.
It does this by checking the `replies` property of a derefenced post, and working through replies, and replies of replies. [See here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies).
This process of thread dereferencing will likely involve making multiple HTTP calls to different servers, especially if the thread is long and complicated.
The end result of this dereferencing is that, assuming the reblogged post by `remote_2` was part of a thread, then `local_account` should now be able to see posts in the thread when they open the status on their home timeline. In other words, they will see replies from accounts on other servers (who they may not have come across yet), in addition to any previous and next posts in the thread as posted by `remote_2`.
This gives `local_account` a more complete view on the conversation, as opposed to just seeing the reblogged post in isolation and out of context. It also gives `local_account` the opportunity to discover new accounts to follow, based on replies to `remote_2`.
## Privacy and Security
During the dereferencing process, GoToSocial signs outgoing requests using the key of the actor who received the activity that necessitated dereferencing. To use the above example, this means that all dereferencing requests would be signed by `local_account`. This gives remote servers the ability to refuse these dereferencing requests, assuming that `local_account` is blocked by one or more participants in the conversation.
From GoToSocial's side, domain blocks will be respected during the dereferencing process, to avoid making calls to servers that `our.server` has blocked.
Individual account blocks will also be respected, meaning that `our.server` won't try to dereference posts from accounts blocked by `local_account`.
Finally, GoToSocial expects that remote servers will only list replies that are marked as public (either `to` or `cc`). GtS may *try* to dereference followers-only posts, but it will assume that remote servers will check whether or not `local_account` is allowed to view them, and refuse accordingly.
Of course, when `local_account` opens up the conversation thread in whatever application they are using, GoToSocial will apply the usual post visibility filtering to ensure that they do not see any posts that they shouldn't have access to.

View file

@ -1,49 +0,0 @@
# ActivityPub Outbox
GoToSocial implements Outboxes for Actors (ie., instance accounts) following the ActivityPub specification [here](https://www.w3.org/TR/activitypub/#outbox).
To get an [OrderedCollection](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection) of Activities that an Actor has published recently, remote servers can do a `GET` request to a user's outbox. The address of this will be something like `https://example.org/users/whatever/outbox`.
The server will return an OrderedCollection of the following structure:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.org/users/whatever/outbox",
"type": "OrderedCollection",
"first": "https://example.org/users/whatever/outbox?page=true"
}
```
Note that the `OrderedCollection` itself contains no items. Callers must dereference the `first` page to start getting items. For example, a `GET` to `https://example.org/users/whatever/outbox?page=true` will produce something like the following:
```json
{
"id": "https://example.org/users/whatever/outbox?page=true",
"type": "OrderedCollectionPage",
"next": "https://example.org/users/whatever/outbox?max_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true",
"prev": "https://example.org/users/whatever/outbox?min_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true",
"partOf": "https://example.org/users/whatever/outbox",
"orderedItems": [
{
"id": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7/activity",
"type": "Create",
"actor": "https://example.org/users/whatever",
"published": "2021-10-18T20:06:18Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.org/users/whatever/followers"
],
"object": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7"
}
]
}
```
The `orderedItems` array will contain up to 30 entries. To get more entries beyond that, the caller can use the `next` link provided in the response.
Note that in the returned `orderedItems`, all activity types will be `Create`. On each activity, the `object` field will be the AP URI of an original public status created by the Actor who owns the Outbox (ie., a `Note` with `https://www.w3.org/ns/activitystreams#Public` in the `to` field, which is not a reply to another status). Callers can use the returned AP URIs to dereference the content of the notes.
Contrary to the ActivityPub spec, GoToSocial will deny requests that are not HTTP signed--that is, unauthenticated requests. This is consistent with GoToSocial's authentication policies for other federation API endpoints. This is to ensure that GoToSocial can deny requests from domains or users that have been blocked either by the GoToSocial instance itself (domain block), or by the individual owner of the Outbox.

View file

@ -0,0 +1,429 @@
# Federating with GoToSocial
Information on the various (ActivityPub) elements needed to federate with GoToSocial.
## HTTP Signatures
GoToSocial requires all `GET` and `POST` requests to ActivityPub s2s endpoints to be accompanied by a valid http signature.
GoToSocial will also sign all outgoing `GET` and `POST` requests that it makes to other servers.
This behavior is the equivalent of Mastodon's [AUTHORIZED_FETCH / "secure mode"](https://docs.joinmastodon.org/admin/config/#authorized_fetch).
GoToSocial uses the [go-fed/httpsig](https://github.com/go-fed/httpsig) library for signing outgoing requests, and for parsing and validating the signatures of incoming requests. This library strictly follows the [Cavage http signature RFC](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures), which is the same RFC used by other implementations like Mastodon, Pixelfed, Akkoma/Pleroma, etc. (This RFC has since been superceded by the [httpbis http signature RFC](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures), but this is not yet widely implemented.)
### Incoming Requests
GoToSocial request signature validation is implemented in [internal/federation](https://github.com/superseriousbusiness/gotosocial/blob/main/internal/federation/authenticate.go).
GoToSocial will attempt to parse the signature using the following algorithms (in order), stopping at the first success:
```text
RSA_SHA256
RSA_SHA512
ED25519
```
### Outgoing Requests
GoToSocial request signing is implemented in [internal/transport](https://github.com/superseriousbusiness/gotosocial/blob/main/internal/transport/signing.go).
When assembling signatures:
- outgoing `GET` requests use `(request-target) host date`
- outgoing `POST` requests use `(request-target) host date digest`
GoToSocial uses the `RSA_SHA256` algorithm for signing requests, which is in line with other ActivityPub implementations.
### Quirks
The `keyId` used by GoToSocial in the `Signature` header will look something like the following:
```text
https://example.org/users/example_user/main-key
```
This is different from most other implementations, which usually use a fragment (`#`) in the `keyId` uri. For example, on Mastodon the user's key would instead be found at:
```text
https://example.org/users/example_user#main-key
```
For Mastodon, the public key of a user is served as part of that user's Actor representation. GoToSocial mimics this behavior when serving the public key of a user, but instead of returning the entire Actor at the `main-key` endpoint (which may contain sensitive fields), will return only a partial stub of the actor. This looks like the following:
```json
{
"@context": [
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams"
],
"id": "https://example.org/users/example_user",
"preferredUsername": "example_user",
"publicKey": {
"id": "https://example.org/users/example_user/main-key",
"owner": "https://example.org/users/example_user",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzGB3yDvMl+8p+ViutVRG\nVDl9FO7ZURYXnwB3TedSfG13jyskoiMDNvsbLoUQM9ajZPB0zxJPZUlB/W3BWHRC\nNFQglE5DkB30GjTClNZoOrx64vLRT5wAEwIOjklKVNk9GJi1hFFxrgj931WtxyML\nBvo+TdEblBcoru6MKAov8IU4JjQj5KUmjnW12Rox8dj/rfGtdaH8uJ14vLgvlrAb\neQbN5Ghaxh9DGTo1337O9a9qOsir8YQqazl8ahzS2gvYleV+ou09RDhS75q9hdF2\nLI+1IvFEQ2ZO2tLk3umUP1ioa+5CWKsWD0GAXbQu9uunAV0VoExP4+/9WYOuP0ei\nKwIDAQAB\n-----END PUBLIC KEY-----\n"
},
"type": "Person"
}
```
Remote servers federating with GoToSocial should extract the public key from the `publicKey` field. Then, they should use the `owner` field of the public key to further dereference the full version of the Actor, using a signed `GET` request.
This behavior was introduced as a way of avoiding having remote servers make unsigned `GET` requests to the full Actor endpoint. However, this may change in future as it is not compliant and causes issues. Tracked in [this issue](https://github.com/superseriousbusiness/gotosocial/issues/1186).
## Access Control
GoToSocial uses access control restrictions to protect users and resources from unwanted interactions with remote accounts and instances.
As shown in the [HTTP Signatures](#http-signatures) section, GoToSocial requires all incoming `GET` and `POST` requests from remote servers to be signed. Unsigned requests will be denied with http code `401 Unauthorized`.
Access control restrictions are implemented by checking the `keyId` of the signature (who owns the public/private key pair making the request).
First, the host value of the `keyId` uri is checked against the GoToSocial instance's list of blocked (defederated) domains. If the host is recognized as a blocked domain, then the http request will immediately be aborted with http code `403 Forbidden`.
Next, GoToSocial will check for the existence of a block (in either direction) between the owner of the public key making the http request, and the owner of the resource that the request is targeting. If the GoToSocial user blocks the remote account making the request, then the request will be aborted with http code `403 Forbidden`.
## Request Throttling & Rate Limiting
GoToSocial applies http request throttling and rate limiting to the ActivityPub API endpoints (inboxes, user endpoints, emojis, etc).
This ensures that remote servers cannot flood a GoToSocial instance with spurious requests. Instead, remote servers making GET or POST requests to the ActivityPub API endpoints should respect 429 and 503 http codes, and take account of the `retry-after` http response header.
For more details on request throttling and rate limiting behavior, please see the [throttling](../api/throttling.md) and [rate limiting](../api/ratelimiting.md) documents.
## Outbox
GoToSocial implements Outboxes for Actors (ie., instance accounts) following the ActivityPub specification [here](https://www.w3.org/TR/activitypub/#outbox).
To get an [OrderedCollection](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection) of Activities that an Actor has published recently, remote servers can do a `GET` request to a user's outbox. The address of this will be something like `https://example.org/users/whatever/outbox`.
The server will return an OrderedCollection of the following structure:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.org/users/whatever/outbox",
"type": "OrderedCollection",
"first": "https://example.org/users/whatever/outbox?page=true"
}
```
Note that the `OrderedCollection` itself contains no items. Callers must dereference the `first` page to start getting items. For example, a `GET` to `https://example.org/users/whatever/outbox?page=true` will produce something like the following:
```json
{
"id": "https://example.org/users/whatever/outbox?page=true",
"type": "OrderedCollectionPage",
"next": "https://example.org/users/whatever/outbox?max_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true",
"prev": "https://example.org/users/whatever/outbox?min_id=01FJC1Q0E3SSQR59TD2M1KP4V8&page=true",
"partOf": "https://example.org/users/whatever/outbox",
"orderedItems": [
{
"id": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7/activity",
"type": "Create",
"actor": "https://example.org/users/whatever",
"published": "2021-10-18T20:06:18Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://example.org/users/whatever/followers"
],
"object": "https://example.org/users/whatever/statuses/01FJC1MKPVX2VMWP2ST93Q90K7"
}
]
}
```
The `orderedItems` array will contain up to 30 entries. To get more entries beyond that, the caller can use the `next` link provided in the response.
Note that in the returned `orderedItems`, all activity types will be `Create`. On each activity, the `object` field will be the AP URI of an original public status created by the Actor who owns the Outbox (ie., a `Note` with `https://www.w3.org/ns/activitystreams#Public` in the `to` field, which is not a reply to another status). Callers can use the returned AP URIs to dereference the content of the notes.
## Conversation Threads
Due to the nature of decentralization and federation, it is practically impossible for any one server on the fediverse to be aware of every post in a given conversation thread.
With that said, it is possible to do 'best effort' dereferencing of threads, whereby remote replies are fetched from one server onto another, to try to more fully flesh out a conversation.
GoToSocial does this by iterating up and down the thread of a conversation, pulling in remote statuses where possible.
Let's say we have two accounts: `local_account` on `our.server`, and `remote_1` on `remote.1`.
In this scenario, `local_account` follows `remote_1`, so posts from `remote_1` show up in the home timeline of `local_account`.
Now, `remote_1` boosts/reblogs a post from a third account, `remote_2`, residing on server `remote.2`.
`local_account` does not follow `remote_2`, and neither does anybody else on `our.server`, which means that `our.server` has not seen this post by `remote_2` before.
![A diagram of the conversation thread, showing the post from remote_2, and possible ancestor and descendant posts](../assets/diagrams/conversation_thread.png)
What GoToSocial will do now, is 'dereference' the post by `remote_2` to check if it is part of a thread and, if so, whether any other parts of the thread can be obtained.
GtS begins by checking the `inReplyTo` property of the post, which is set when a post is a reply to another post. [See here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto). If `inReplyTo` is set, GoToSocial derefences the replied-to post. If *this* post also has an `inReplyTo` set, then GoToSocial dereferences that too, and so on.
Once all of these **ancestors** of a status have been retrieved, GtS will begin working down through the **descendants** of posts.
It does this by checking the `replies` property of a derefenced post, and working through replies, and replies of replies. [See here](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies).
This process of thread dereferencing will likely involve making multiple HTTP calls to different servers, especially if the thread is long and complicated.
The end result of this dereferencing is that, assuming the reblogged post by `remote_2` was part of a thread, then `local_account` should now be able to see posts in the thread when they open the status on their home timeline. In other words, they will see replies from accounts on other servers (who they may not have come across yet), in addition to any previous and next posts in the thread as posted by `remote_2`.
This gives `local_account` a more complete view on the conversation, as opposed to just seeing the reblogged post in isolation and out of context. It also gives `local_account` the opportunity to discover new accounts to follow, based on replies to `remote_2`.
## Reports / Flags
Like other microblogging ActivityPub implementations, GoToSocial uses the [Flag](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-flag) Activity type to communicate user moderation reports to other servers.
### Outgoing
The json of an outgoing GoToSocial `Flag` looks like the following:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "http://example.org/users/example.org",
"content": "dark souls sucks, please yeet this nerd",
"id": "http://example.org/reports/01GP3AWY4CRDVRNZKW0TEAMB5R",
"object": [
"http://fossbros-anonymous.io/users/foss_satan",
"http://fossbros-anonymous.io/users/foss_satan/statuses/01FVW7JHQFSFK166WWKR8CBA6M"
],
"type": "Flag"
}
```
The `actor` of the `Flag` will always be the instance actor of the GoToSocial instance on which the `Flag` was created. This is done to preserve partial anonymity of the user who created the report, in order to prevent them becoming a target for harassment.
The `content` of the `Flag` is a piece of text submitted by the user who created the `Flag`, which should give remote instance admins a reason why the report was created. This may be an empty string, or may not be present on the json, if no reason was submitted by the user.
The value of the `object` field of the `Flag` will either be a string (the ActivityPub `id` of the user being reported), or it will be an array of strings, where the first entry in the array is the `id` of the reported user, and subsequent entries are the `id`s of one or more reported `Note`s / statuses.
The `Flag` activity is delivered as-is to the `inbox` (or shared inbox) of the reported user. It is not wrapped in a `Create` activity.
### Incoming
GoToSocial assumes incoming reports will be delivered as a `Flag` Activity to the `inbox` of the account being reported. It will parse the incoming `Flag` following the same formula that it uses for creating outgoing `Flag`s, with one difference: it will attempt to parse status URLs from both the `object` field, and from a Misskey/Calckey-formatted `content` value, which includes in-line status URLs.
GoToSocial will not assume that the `to` field will be set on an incoming `Flag` activity. Instead, it assumes that remote instances use `bto` to direct the `Flag` to its recipient.
A valid incoming `Flag` Activity will be made available as a report to the admin(s) of the GoToSocial instance that received the report, so that they can take any necessary moderation action against the reported user.
The reported user themself will not see the report, or be notified that they have been reported, unless the GtS admin chooses to share this information with them via some other channel.
## Featured (aka pinned) Posts
GoToSocial allows users to feature (or 'pin') posts on their profile.
In ActivityPub terms, GoToSocial serves these pinned posts as an [OrderedCollection](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-orderedcollection) at the endpoint indicated in an Actor's [featured](https://docs.joinmastodon.org/spec/activitypub/#featured) field. The value of this field will be set to something like `https://example.org/users/some_user/collections/featured`.
By making a signed GET request to this endpoint, remote instances can dereference the featured posts collection, which will return an `OrderedCollection` with a list of post URIs in the `orderedItems` field.
Example of a featured collection of a user who has pinned multiple `Note`s:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.org/users/some_user/collections/featured",
"orderedItems": [
"https://example.org/users/some_user/statuses/01GS7VTYH0S77NNXTP6W4G9EAG",
"https://example.org/users/some_user/statuses/01GSFY2SZK9TPCJFQ1WCCPGDRT",
"https://example.org/users/some_user/statuses/01GSCXY70MZCBFMH5EKJW9ENC8"
],
"totalItems": 3,
"type": "OrderedCollection"
}
```
Example of a user who has pinned one `Note`:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.org/users/some_user/collections/featured",
"orderedItems": [
"https://example.org/users/some_user/statuses/01GS7VTYH0S77NNXTP6W4G9EAG"
],
"totalItems": 1,
"type": "OrderedCollection"
}
```
Example with no pinned `Note`s:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://example.org/users/some_user/collections/featured",
"orderedItems": [],
"totalItems": 0,
"type": "OrderedCollection"
}
```
Unlike Mastodon and some other implementations, GoToSocial does *not* serve full `Note` representations as `orderedItems` values. Instead, it provides just the URI of each `Note`, which the remote server can then dereference (or not, if they already have the `Note` cached locally).
Some of the URIs served as part of the collection may point to followers-only posts which the requesting `Actor` won't necessarily have permission to view. Remote servers should make sure to do their own filtering (as with any other post type) to ensure that these posts are only shown to users who are permitted to view them.
Another difference between GoToSocial and other server implementations is that GoToSocial does not send updates to remote servers when a post is pinned or unpinned by a user. Mastodon does this by sending [Add](https://www.w3.org/TR/activitypub/#add-activity-inbox) and [Remove](https://www.w3.org/TR/activitypub/#remove-activity-inbox) Activity types where the `object` is the post being pinned or unpinned, and the `target` is the sending `Actor`'s `featured` collection. While this conceptually makes sense, it is not in line with what the ActivityPub protocol recommends, since the `target` of the Activity "is not owned by the receiving server, and thus they can't update it".
Instead, to build a view of a GoToSocial user's pinned posts, it is recommended that remote instances simply poll a GoToSocial Actor's `featured` collection every so often, and add/remove posts in their cached representation as appropriate.
## Post Deletes
GoToSocial allows users to delete posts that they have created. These deletes will be federated out to other instances, which are expected to also delete their local cache of the post.
### Outgoing
When a post is deleted by a GoToSocial user, the server will send a `Delete` activity out to other instances.
The `Delete` will have the ActivityPub URI of the post set as the value of the `Object` entry.
`to` and `cc` will be set according to the visibility of the original post, and any users mentioned/replied to by the original post.
If the original post was not a direct message, the ActivityPub `Public` URI will be addressed in `to`. Otherwise, only mentioned and replied to users will be addressed.
In the following example, the 'admin' user deletes a public post of theirs in which the 'foss_satan' user was mentioned:
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "http://example.org/users/admin",
"cc": [
"http://example.org/users/admin/followers",
"http://fossbros-anonymous.io/users/foss_satan"
],
"object": "http://example.org/users/admin/statuses/01FF25D5Q0DH7CHD57CTRS6WK0",
"to": "https://www.w3.org/ns/activitystreams#Public",
"type": "Delete"
}
```
In the next example, the '1happyturtle' user deletes a direct message which was originally addressed to the 'the_mighty_zork' user.
```json
{
"@context": "https://www.w3.org/ns/activitystreams",
"actor": "http://example.org/users/1happyturtle",
"cc": [],
"object": "http://example.org/users/1happyturtle/statuses/01FN3VJGFH10KR7S2PB0GFJZYG",
"to": "http://somewhere.com/users/the_mighty_zork",
"type": "Delete"
}
```
To process a `Delete` activity coming from a GoToSocial instance, remote instances should check if they have the `Object` stored according to the provided URI. If they do, they should remove it from their local cache. If not, then no action is required, since they never had the now-deleted post stored in the first place.
### Incoming
GoToSocial processes `Delete` activities coming in from remote instances as thoroughly as possible in order to respect the privacy of other users.
When a GoToSocial instance receives a `Delete`, it will attempt to derive the deleted post URI from the `Object` field. If the `Object` is just a URI, then this URI will be taken. If the `Object` is a `Note` or another type commonly used to represent a post, then the URI will be extracted from it.
Then, GoToSocial will check if it has a post stored with the given URI. If it does, it will be completely deleted from the database and all user timelines.
GoToSocial will only delete a post if it can be sure that the original post was owned by the `actor` that the `Delete` is attributed to.
## Profile Fields
Like Mastodon and other fediverse softwares, GoToSocial lets users set key/value pairs on their profile; useful for conveying short pieces of information like links, pronouns, age, etc.
For the sake of compatibility with other implementations, GoToSocial uses the same schema.org PropertyValue extension that Mastodon uses, present as an `attachment` array value on `actor`s that have fields set. For example, the below JSON shows an account with two PropertyValue fields:
```json
{
"@context": [
"http://joinmastodon.org/ns",
"https://w3id.org/security/v1",
"https://www.w3.org/ns/activitystreams",
"http://schema.org"
],
"attachment": [
{
"name": "should you follow me?",
"type": "PropertyValue",
"value": "maybe!"
},
{
"name": "age",
"type": "PropertyValue",
"value": "120"
}
],
"discoverable": false,
"featured": "http://example.org/users/1happyturtle/collections/featured",
"followers": "http://example.org/users/1happyturtle/followers",
"following": "http://example.org/users/1happyturtle/following",
"id": "http://example.org/users/1happyturtle",
"inbox": "http://example.org/users/1happyturtle/inbox",
"manuallyApprovesFollowers": true,
"name": "happy little turtle :3",
"outbox": "http://example.org/users/1happyturtle/outbox",
"preferredUsername": "1happyturtle",
"publicKey": {
"id": "http://example.org/users/1happyturtle#main-key",
"owner": "http://example.org/users/1happyturtle",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtTc6Jpg6LrRPhVQG4KLz\n2+YqEUUtZPd4YR+TKXuCnwEG9ZNGhgP046xa9h3EWzrZXaOhXvkUQgJuRqPrAcfN\nvc8jBHV2xrUeD8pu/MWKEabAsA/tgCv3nUC47HQ3/c12aHfYoPz3ufWsGGnrkhci\nv8PaveJ3LohO5vjCn1yZ00v6osMJMViEZvZQaazyE9A8FwraIexXabDpoy7tkHRg\nA1fvSkg4FeSG1XMcIz2NN7xyUuFACD+XkuOk7UqzRd4cjPUPLxiDwIsTlcgGOd3E\nUFMWVlPxSGjY2hIKa3lEHytaYK9IMYdSuyCsJshd3/yYC9LqxZY2KdlKJ80VOVyh\nyQIDAQAB\n-----END PUBLIC KEY-----\n"
},
"summary": "\u003cp\u003ei post about things that concern me\u003c/p\u003e",
"tag": [],
"type": "Person",
"url": "http://example.org/@1happyturtle"
}
```
For `actor`s that have no `PropertyValue` fields set, the `attachment` property will not be set at all. That is, the `attachment` key value will not be present on the `actor` (not even as an empty array or null value).
While `attachment` is not technically an ordered collection, GoToSocial--again, in line with what other implementations do--does present `attachment` `PropertyValue` fields in the order in which they should to be displayed.
GoToSocial will also parse PropertyValue fields from remote `actor`s discovered by the GoToSocial instance, to allow them to be displayed to users on the GoToSocial instance.
GoToSocial allows up to 6 `PropertyValue` fields by default, as opposed to Mastodon's default 4.
## Hashtags
GoToSocial users can include hashtags in their posts, which indicate to other instances that that user wishes their post to be grouped together with other posts using the same hashtag, for discovery purposes.
In line with other ActivityPub server implementations, GoToSocial implicitly expects that only public-addressed posts will be grouped by hashtag.
To federate hashtags in and out, GoToSocial uses the widely-adopted [ActivityStreams `Hashtag` type extension](https://www.w3.org/wiki/Activity_Streams_extensions#as:Hashtag_type) in the `tag` property of objects.
Here's what the `tag` property might look like on an outgoing message that uses one custom emoji, and one tag:
```json
"tag": [
{
"icon": {
"mediaType": "image/png",
"type": "Image",
"url": "https://example.org/fileserver/01AY6P665V14JJR0AFVRT7311Y/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png"
},
"id": "https://example.org/emoji/01F8MH9H8E4VG3KDYJR9EGPXCQ",
"name": ":rainbow:",
"type": "Emoji",
"updated": "2021-09-20T10:40:37Z"
},
{
"href": "https://example.org/tags/welcome",
"name": "#welcome",
"type": "Hashtag"
}
]
```
With just one tag, the `tag` property will be an object rather than an array, which will look like this:
```json
"tag": {
"href": "https://example.org/tags/welcome",
"name": "#welcome",
"type": "Hashtag"
}
```
### Hashtag `href` property
The `href` URL provided by GoToSocial in outgoing tags points to a web URL that serves `text/html`.
GoToSocial makes no guarantees whatsoever about what the content of the given `text/html` will be, and remote servers should not interpret the URL as a canonical ActivityPub ID/URI property. The `href` URL is provided merely as an endpoint which *might* contain more information about the given hashtag.

View file

@ -1,7 +0,0 @@
# Security
TODO: describe the security model we use for federation.
* http signatures
* behavior for refusing requests
* how data is protected

View file

@ -0,0 +1,75 @@
# Deployment considerations
Before deploying GoToSocial, it's important to think through a few things as some choices will have long-term consequences for how you run and manage GoToSocial.
!!! danger
It's not supported across the Fediverse to switch between implementations on the same domain. This means that if you run GoToSocial on example.org, you'll run into federation issues if you try to switch to a different implementation like Pleroma/Akkoma, Misskey/Calckey etc.
In that same vein, if you already have another ActivityPub implementation running on example.org you should not attempt to switch to GoToSocial on that domain.
## Database
GoToSocial supports both SQLite and Postgres and you can start using either. We do not currently have tooling to support migrating from SQLite to Postgres or vice-versa, but it is possible in theory.
SQLite is great for a single-user instance. If you're planning on hosting multiple people it's advisable to use Postgres instead. You can always use Postgres regardless of the instance size.
!!! tip
Please [backup your database](../admin/backup_and_restore.md). The database contains encryption keys for the instance and any user accounts. You won't be able to federate again from the same domain if you lose these keys.
## Domain name
In order to federate with others, you'll need a domain like `example.org`. You can register your domain name through any domain registrar, like [Namecheap](https://www.namecheap.com/). Make sure you pick a registrar that also lets you manage DNS entries, so you can point your domain to the IP of the server that's running your GoToSocial instance.
You'll commonly see usernames existing at the apex of the domain, for example `@me@example.org` but this is not required. It's perfectly fine to have users exist on `@me@social.example.org` instead. Many people prefer to have usernames on the apex as its shorter to type, but you can use any (subdomain) you control.
It is possible to have usernames like `@me@example.org` but have GoToSocial running on `social.example.org` instead. This is done by distinguishing between the API domain, called the "host", and the domain used for usernames, called the "account domain".
!!! danger
It's not possible to safely change whether the host and account domain are different after the fact. It requires regenerating the database and will cause confusion for any server you have already federated with.
When using a single domain, you only need to configure the "host" in the GoToSocial configuration:
```yaml
host: "example.org"
```
When using a split domain approach, you need to configure both the "host" and the "account-domain":
```yaml
host: "social.example.org"
account-domain: "example.org"
```
## TLS
For federation to work, you have to use TLS. Most implementations, including GoToSocial, will generally refuse to federate over unencrypted transports.
GoToSocial comes with built-in support for provisioning certificates through Lets Encrypt. It can also load certificates from disk. If you have a reverse-proxy in front of GoToSocial you can handle TLS at that level instead.
!!! tip
Make sure you configure the use of modern versions of TLS, TLSv1.2 and higher, in order to keep communications between servers and clients safe. When GoToSocial handles TLS termination this is done automatically for you. If you have a reverse-proxy in use, use the [Mozilla SSL Configuration Generator](https://ssl-config.mozilla.org/).
## Server / VPS
GoToSocial aims to fit in small spaces so we try and ensure that the system requirements are fairly minimal: for a single-user instance with about 100 followers/followees, it uses somewhere between 50 to 100MB of RAM. CPU usage is only intensive when handling media (encoding blurhashes, mostly) and/or doing a lot of federation requests at the same time.
These light requirements mean GtS runs pretty well on something like a Raspberry Pi (a €40 single-board computer). It's been tested on a Raspberry Pi Zero W as well (a €9 computer smaller than a credit card), but it's not quite able to run on that. It should run on a Raspberry Pi Zero W 2 (which costs €14!), but we haven't tested that yet. You can also repurpose an old laptop or desktop to run GoToSocial for you.
If you decide to use a VPS instead, you can spin yourself up something cheap with Linux running on it. Most of the VPS offerings in the €2-€5 range will perform admirably for a personal GoToSocial instance.
[Hostwinds](https://www.hostwinds.com/) is a good option here: it's cheap and they throw in a static IP address for free.
[Greenhost](https://greenhost.net) is also great: it has zero CO2 emissions, but is a bit more costly.
## Ports
GoToSocial needs ports `80` and `443` open.
* `80` is used for Lets Encrypt. As such, you don't need it if you don't use the built-in Lets Encrypt provisioning.
* `443` is used to serve the API on with TLS and is what any instance you're federating with will try to connect to.
If you can't leave `443` and `80` open on the machine, don't worry! You can configure these ports in GoToSocial, but you'll have to also configure port forwarding to properly forward traffic on `443` and `80` to whatever ports you choose.
!!! tip
You should configure a firewall on your machine, as well as some protection against brute-force SSH login attempts and the like. Take a look at our [firewall documentation](../advanced/security/firewall.md) for pointers on what to configure and tools that can help you out.

View file

@ -0,0 +1,123 @@
# Container
This guide walks you through getting GoToSocial up and running using the official container images we publish. In this case we'll be using the Docker runtime directly through [Docker Compose](https://docs.docker.com/compose) together with SQLite as the database.
You can also run GoToSocial using a container orchestration system such as [Kubernetes](https://kubernetes.io/) or [Nomad](https://www.nomadproject.io/), but that is beyond the scope of this guide.
## Create a Working Directory
You need a working directory in which your docker-compose file will be located, and a directory for GoToSocial to store data in, so create these directories with the following command:
```bash
mkdir -p ~/gotosocial/data
```
Now change to the working directory you created:
```bash
cd ~/gotosocial
```
## Get the latest docker-compose.yaml
Use `wget` to download the latest [docker-compose.yaml](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/docker-compose/docker-compose.yaml) example, which we'll customize for our needs:
```bash
wget https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/docker-compose/docker-compose.yaml
```
## Edit the docker-compose.yaml
Because GoToSocial can be configured using [Environment Variables](../../configuration/index.md#environment-variables), we can skip mounting a config.yaml file into the container, to make our configuration simpler. We just need to edit the docker-compose.yaml file to change a few things.
First open the docker-compose.yaml file in your editor of choice. For example:
```bash
nano docker-compose.yaml
```
### Version
If desired, update the GoToSocial Docker image tag to the version of GtS you want to use.
`latest` - the default. This points to the latest stable release of GoToSocial.
`snapshot` - points to whatever code is currently on the main branch. Not guaranteed to be stable, and may often be broken. Use with caution.
!!! tip
You can also replace `latest` with a specific GoToSocial version number. This is recommended when you want to make sure that you don't update your GoToSocial version by accident, which can cause problems. The list of releases can be found [right here](https://github.com/superseriousbusiness/gotosocial/releases), with the newest release at the top. Replace `latest` in the docker-compose.yaml with the number of the desired release (without the leading `v` or trailing version name).
### Host
Change the `GTS_HOST` environment variable to the domain you are running GoToSocial on.
### Server Timezone (optional but recommended)
To ensure that your GoToSocial server displays the correct time on posts and in logs, you can set the timezone of the server by editing the `TZ` environment variable.
1. Remove the `#` before `TZ: UTC` in the environment section.
2. Change the `UTC` part to your timezone identifier. For a list of these identifiers, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.
For example, if you are running your server in Minsk, you would set `TZ: Europe/Minsk`, Japan would be `TZ: Japan`, Dubai would be `TZ: Asia/Dubai`, etc.
If you don't set this, the default `UTC` will be used.
### User (optional / probably not necessary)
By default, Dockerized GoToSocial runs with Linux user/group `1000:1000`, which is fine in most cases. If you want to run as a different user/group, you should change the `user` field in the docker-compose.yaml accordingly.
For example, let's say you created the `~/gotosocial/data` directory for a user with id `1001`, and group id `1001`. If you now try to run GoToSocial without changing the `user` field, it will get a permissions error trying to open its database file in the directory. In this case, you would have to change the `user` field of the docker compose file to `1001:1001`.
### LetsEncrypt (optional)
If you want to use [LetsEncrypt](../../configuration/tls.md) for TLS certificates (https), you should also:
1. Change the value of `GTS_LETSENCRYPT_ENABLED` to `"true"`.
2. Remove the `#` before `- "80:80"` in the `ports` section.
3. (Optional) Set `GTS_LETSENCRYPT_EMAIL_ADDRESS` to a valid email address to receive certificate expiry warnings etc.
## Start GoToSocial
With those small changes out of the way, you can now start GoToSocial with the following command:
```shell
docker-compose up -d
```
After running this command, you should get an output like:
```text
Creating network "gotosocial_gotosocial" with the default driver
Creating gotosocial ... done
```
If you want to follow the logs of GoToSocial, you can use:
```bash
docker logs -f gotosocial
```
If everything is OK, you should see something similar to the following:
```text
time=2022-04-19T09:48:35Z level=info msg=connected to SQLITE database
time=2022-04-19T09:48:35Z level=info msg=MIGRATED DATABASE TO group #1 (20211113114307, 20220214175650, 20220305130328, 20220315160814) func=doMigration
time=2022-04-19T09:48:36Z level=info msg=instance account example.org CREATED with id 01EXX0TJ9PPPXF2C4N2MMMVK50
time=2022-04-19T09:48:36Z level=info msg=created instance instance example.org with id 01PQT31C7BZJ1Q2Z4BMEV90ZCV
time=2022-04-19T09:48:36Z level=info msg=media manager cron logger: start[]
time=2022-04-19T09:48:36Z level=info msg=media manager cron logger: schedule[now 2022-04-19 09:48:36.096127852 +0000 UTC entry 1 next 2022-04-20 00:00:00 +0000 UTC]
time=2022-04-19T09:48:36Z level=info msg=started media manager remote cache cleanup job: will run next at 2022-04-20 00:00:00 +0000 UTC
time=2022-04-19T09:48:36Z level=info msg=listening on 0.0.0.0:8080
```
## Create your first User
Now that GoToSocial is running, you should create at least a user for yourself. How to do so is documented in our [Creating users](../user_creation.md) guide.
### Done
GoToSocial should now be running on your machine! To verify this, open your browser navigate to whatever you set as your `GTS_HOST` value. You should see the GoToSocial landing page. Well done!
## (Optional) Reverse Proxy
If you want to run other webservers on port 443 or want to add an additional layer of security you might want to use a [reverse proxy](../reverse_proxy/index.md). We have guides available for a couple of popular open source options and will gladly take pull requests to add more.

View file

@ -0,0 +1,14 @@
# Installation
As we noted in [Releases](../releases.md), we publish official binary release as well as containers. We have a number of guides available on how to deploy your own GoToSocial instance this way.
Before proceeding with your installation, please ensure you've read through the [Deployment considerations](../index.md) first and have a domain and server ready to go.
Also take a minute to familiarise yourself with [how to configure](../../configuration/index.md) GoToSocial.
## Guides
For third-party releases we don't provide guides on how to use them. You need to refer to their own documentation instead. Our guides might still be useful to review in order to familiarise yourself with which configuration options you likely want to set and tweak.
* [Bare metal](metal.md)
* [Container](container.md)

View file

@ -0,0 +1,123 @@
# Bare metal
This guide walks you through getting GoToSocial up and running on bare metal using the official binary releases.
## Prepare VPS
In a terminal on the VPS or your homeserver, make the directory that GoToSocial will run from, the directory it will use as storage, and the directory it will store LetsEncrypt certificates in:
```bash
mkdir /gotosocial && mkdir /gotosocial/storage && mkdir /gotosocial/storage/certs
```
If you don't have root permissions on the machine, use something like `~/gotosocial` instead.
## Download Release
In a terminal on the VPS or your homeserver, cd into the base directory for GoToSocial you just created above:
```bash
cd /gotosocial
```
Now, download the latest GoToSocial release archive corresponding to the operating system and architecture you're running on.
(You can find the list of releases [right here](https://github.com/superseriousbusiness/gotosocial/releases), arranged with the newest release at the top.)
For example, to download version 0.5.2 for running on 64-bit Linux:
```bash
wget https://github.com/superseriousbusiness/gotosocial/releases/download/v0.5.2/gotosocial_0.5.2_linux_amd64.tar.gz
```
Then extract it:
```bash
tar -xzf gotosocial_0.5.2_linux_amd64.tar.gz
```
This will put the `gotosocial` binary in your current directory, in addition to the `web` folder, which contains assets for the web frontend, and an `example` folder, which contains a sample configuration file.
## Edit Configuration File
Copy the configuration file from the example folder into your current directory:
```bash
cp ./example/config.yaml .
```
Now open the file in your text editor of choice so that you can set some important configuration values. Change the following settings:
- Set `host` to whatever hostname you're going to be running the server on (eg., `example.org`).
- Set `port` to `443`.
- Set `db-type` to `sqlite`.
- Set `db-address` to `sqlite.db`.
- Set `storage-local-base-path` to the storage directory you created above (eg., `/gotosocial/storage`).
- Set `letsencrypt-enabled` to `true`.
- Set `letsencrypt-cert-dir` to the certificate storage directory you created above (eg., `/gotosocial/storage/certs`).
The above options assume you're using SQLite as your database. If you want to use Postgres instead, see [here](../../configuration/database.md) for the config options.
## Run the Binary
You can now run the binary.
Start the GoToSocial server with the following command:
```bash
./gotosocial --config-path ./config.yaml server start
```
The server should now start up and you should be able to access the splash page by navigating to your domain in the browser. Note that it might take up to a minute or so for your LetsEncrypt certificates to be created for the first time, so refresh a few times if necessary.
Note that for this example we're assuming that we're allowed to run on port 443 (standard https port), and that nothing else is running on this port.
## Create your user
You can use the GoToSocial binary to also create and promote your user account. This is all documented in our [Creating users](../user_creation.md) guide.
## Login
You should now be able to log in to your instance using the email address and password of the account you just created. We recommend using [Semaphore](https://semaphore.social) or [Tusky](https://tusky.app) for this.
## (Optional) Enable the systemd service
If you don't like manually starting GoToSocial on every boot you might want to create a systemd service that does that for you.
First stop your GoToSocial instance.
Then create a new user and group for your GoToSocial installation:
```bash
sudo useradd -r gotosocial
sudo groupadd gotosocial
sudo usermod -a -G gotosocial gotosocial
```
Then make them the owner of your GoToSocial installation since they will need to read and write in it:
```bash
sudo chown -R gotosocial:gotosocial /gotosocial
```
You can find a `gotosocial.service` file in the `example` folder on [github](https://raw.githubusercontent.com/superseriousbusiness/gotosocial/main/example/gotosocial.service) or your installation.
Copy it to `/etc/systemd/system/gotosocial.service`:
```bash
sudo cp /gotosocial/example/gotosocial.service /etc/systemd/system/
```
Then use `sudoedit /etc/systemd/system/gotosocial.service` to change the `ExecStart=` and `WorkingDirectory=` lines according to your installation.
If you have been following this guide word for word the defaults should be fine.
After you're done enable the service:
```bash
sudo systemctl enable --now gotosocial.service
```
## (Optional) Reverse proxy
If you want to run other webservers on port 443 or want to add an additional layer of security you might want to use a [reverse proxy](../reverse_proxy/index.md). We have guides available for a couple of popular open source options and will gladly take pull requests to add more.

View file

@ -0,0 +1,40 @@
# Releases
GoToSocial can be installed in a number of different ways. We publish official binary releases as well as container images. A number of third-party packages are maintained by different distributions and some people have created additional deployment tooling to make it easy to deploy GoToSocial yourself.
## Binary releases
We publish binary builds for Linux to [our GitHub project](https://github.com/superseriousbusiness/gotosocial/releases):
* 32-bit Intel/AMD (i386/x86)
* 64-bit Intel/AMD (amd64/x86_64)
* 32-bit ARM (v6 and v7)
* 64-bit ARM64
For FreeBSD we publish:
* 64-bit Intel/AMD (amd64/x86_64)
## Containers
We also publish container images [on the Docker Hub](https://hub.docker.com/r/superseriousbusiness/gotosocial).
Containers are released for the same Linux platforms as our binary releases, with the exception of 32-bit Intel/AMD.
## Third-party
Some folks have created distribution packages for GoToSocial or additional tooling to aid in installing GoToSocial.
### Distribution packages
These packages are not maintained by GoToSocial, so please direct questions and issues to the repository maintainers (and donate to them!).
[![Packaging status](https://repology.org/badge/vertical-allrepos/gotosocial.svg)](https://repology.org/project/gotosocial/versions)
### Deployment tools
You can deploy your own instance of GoToSocial with the help of:
- [YunoHost GoToSocial Packaging](https://github.com/YunoHost-Apps/gotosocial_ynh) by [OniriCorpe](https://github.com/OniriCorpe).
- [Ansible Playbook (MASH)](https://github.com/mother-of-all-self-hosting/mash-playbook): The playbook supports a many services, including GoToSocial. [Documentation](https://github.com/mother-of-all-self-hosting/mash-playbook/blob/main/docs/services/gotosocial.md)
- GoToSocial Helm Charts:
- [GoToSocial Helm Chart](https://github.com/fSocietySocial/charts/tree/main/charts/gotosocial) by [0hlov3](https://github.com/0hlov3).

View file

@ -0,0 +1,248 @@
# Apache HTTP Server
In order to use Apache as a reverse proxy for GoToSocial you'll need to have it installed on your server. If you intend for the Apache instance to also handle TLS, you'll need to [provision TLS certificates](../../advanced/certificates.md) too.
Apache is [packaged for many distributions](https://repology.org/project/apache/versions). It's very likely you can install it with your distribution's package manager. You can also run Apache using a container runtime with the [official Apache image](https://hub.docker.com/_/httpd) that's published to the Docker Hub.
In this guide we'll also show how to use certbot to provision the TLS certificates. It too is [packaged in many distributions](https://repology.org/project/certbot/versions) but many distributions tend to ship fairly old versions of certbot. If you run into trouble it may be worth considering using the [container image](https://hub.docker.com/r/certbot/certbot) instead.
## Configure GoToSocial
We're going to have Apache handle LetsEncrypt certificates, so you need to turn off built-in LetsEncrypt support in your GoToSocial config.
First open the file in your text editor:
```bash
sudoedit /gotosocial/config.yaml
```
Then set `letsencrypt-enabled: false`.
If the reverse proxy will be running on the same machine, set the `bind-address` to `"localhost"` so that the GoToSocial server is only accessible via loopback. Otherwise it may be possible to bypass your proxy by connecting to GoToSocial directly, which might be undesirable.
If GoToSocial is already running, restart it.
```bash
sudo systemctl restart gotosocial.service
```
Or if you don't have a systemd service just restart it manually.
## Set up Apache
### Required Apache modules
You need to ensure you have a number of Apache modules installed and enabled. All these modules *should* ship with your distribution's Apache package, but they may have been split out into separate packages.
You can check which modules you have installed with `apachectl -M`.
You'll need to have the following modules loaded:
* `proxy_http` to proxy HTTP requests to GoToSocial
* `ssl` to handle SSL/TLS
* `headers` to manipulate HTTP request and response headers
* `rewrite` to rewrite HTTP requests
* `md` for Lets Encrypt, available since 2.4.30
On Debian, Ubuntu and openSUSE, you can use the [`a2enmod`](https://manpages.debian.org/bookworm/apache2/a2enmod.8.en.html) utility to load any additional modules. For the Red Hat/CentOS family of distributions, you'll need to add a [`LoadModule` directive](https://httpd.apache.org/docs/2.4/mod/mod_so.html#loadmodule) to your Apache configuration instead.
### TLS with mod_md
!!! note
`mod_md` is only available since Apache 2.4.30 and still considered experimental. It works well enough in practice and is the most convenient method.
Now we'll configure Apache HTTP Server to serve GoToSocial requests.
First we'll write a configuration for Apache HTTP Server and put it in `/etc/apache2/sites-available`:
```bash
sudo mkdir -p /etc/apache2/sites-available/
sudoedit /etc/apache2/sites-available/example.com.conf
```
In the above `sudoedit` command, replace `example.com` with the hostname of your GoToSocial server.
The file you're about to create should look a bit like this:
```apache
MDomain example.com auto
MDCertificateAgreement accepted
<VirtualHost *:80 >
ServerName example.com
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
# set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758
RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L]
SSLEngine On
ProxyPreserveHost On
# set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set "X-Forwarded-Proto" expr=https
</VirtualHost>
```
or, if you have [Apache httpd 2.4.47+](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#protoupgrade), you can get rid of both `mod_rewrite` and `mod_proxy_wstunnel` and simplify the whole config to:
```apache
MDomain example.com auto
MDCertificateAgreement accepted
<VirtualHost *:80 >
ServerName example.com
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
SSLEngine On
ProxyPreserveHost On
# set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758
ProxyPass / http://127.0.0.1:8080/ upgrade=websocket
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set "X-Forwarded-Proto" expr=https
</VirtualHost>
```
Again, replace occurrences of `example.com` in the above config file with the hostname of your GtS server. If your domain name is `gotosocial.example.com`, then `gotosocial.example.com` would be the correct value.
You should also change `http://127.0.0.1:8080` to the correct address and port (if it's not on `127.0.0.1:8080`) of your GtS server. For example, if you're running GoToSocial on another machine with the local ip of `192.168.178.69` and on port `8080` then `http://192.168.178.69:8080/` would be the correct value.
`Rewrite*` directives are needed to ensure that Websocket streaming connections also work. See the [websocket](./websocket.md) document for more information on this.
`ProxyPreserveHost On` is essential: It guarantees that the proxy and the GoToSocial speak of the same Server name. If not, GoToSocial will build the wrong authentication headers, and all attempts at federation will be rejected with 401 Unauthorized.
By default, apache sets `X-Forwarded-For` in forwarded requests. To make this and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../../api/ratelimiting.md) and [general configuration](../../configuration/general.md) docs
Save and close the config file.
Now we'll need to link the file we just created to the folder that Apache HTTP Server reads configurations for active sites from.
```bash
sudo mkdir /etc/apache2/sites-enabled
sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/
```
In the above `ln` command, replace `example.com` with the hostname of your GoToSocial server.
Now check for configuration errors.
```bash
sudo apachectl -t
```
If everything is fine you should get this as output:
```text
Syntax OK
```
Everything working? Great! Then restart Apache HTTP Server to load your new config file.
```bash
sudo systemctl restart apache2
```
Now, monitor the logs to see when the new LetsEncrypt certificate arrives (`tail -F /var/log/apache2/error.log`), and then reload Apache one last time with the above `systemctl restart` command. After that you should be good to go!
Apache HTTP Server needs to be restart (or reloaded), every time `mod_md` gets a new certificate; see the module's docs for [more information](https://github.com/icing/mod_md#how-to-manage-server-reloads).
Depending on your version of Apache HTTP Server, you may see the following error: `error (specific information not available): acme problem urn:ietf:params:acme:error:invalidEmail: Error creating new account :: contact email "webmaster@localhost" has invalid domain : Domain name needs at least one dot`
If this happens, you'll need to do one (or all) of the below:
1. Update `/etc/apache2/sites-enabled/000-default.conf` and change the `ServerAdmin` value to a valid email address (then reload Apache HTTP Server).
2. Add the line `MDContactEmail your.email.address@whatever.com` below the `MDomain` line in `/etc/apache2/sites-available/example.com.conf`, replacing `your.email.address@whatever.com` with a valid email address, and `example.com` with your GtS host name.
### TLS with externally managed certificates
!!! note
We have additional documentation on how to [provision TLS certificates](../../advanced/certificates.md) that also provides links to additional content and tutorials for different distributions that may be good to review.
If you prefer to have a manual setup or setting SSL using a different service to manage it (Certbot, etc), then you can use a simpler setup for your Apache HTTP Server.
First we'll write a configuration for Apache HTTP Server and put it in `/etc/apache2/sites-available`:
```bash
sudo mkdir -p /etc/apache2/sites-available/
sudoedit /etc/apache2/sites-available/example.com.conf
```
In the above `sudoedit` command, replace `example.com` with the hostname of your GoToSocial server.
The file you're about to create should look initially for both 80 (required) and 443 ports (optional) a bit like this:
```apache
<VirtualHost *:80>
ServerName example.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
# set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758
RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L]
ProxyPreserveHost On
# set to 127.0.0.1 instead of localhost to work around https://stackoverflow.com/a/52550758
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>
```
Again, replace occurrences of `example.com` in the above config file with the hostname of your GtS server. If your domain name is `gotosocial.example.com`, then `gotosocial.example.com` would be the correct value.
You should also change `http://127.0.0.1:8080` to the correct address and port (if it's not on `127.0.0.1:8080`) of your GtS server. For example, if you're running GoToSocial on another machine with the local ip of `192.168.178.69` and on port `8080` then `http://192.168.178.69:8080/` would be the correct value.
`Rewrite*` directives are needed to ensure that Websocket streaming connections also work. See the [websocket](websocket.md) document for more information on this.
`ProxyPreserveHost On` is essential: It guarantees that the proxy and the GoToSocial speak of the same Server name. If not, GoToSocial will build the wrong authentication headers, and all attempts at federation will be rejected with 401 Unauthorized.
In the case of providing an initial setup for the 443 port looking for additional managing by an external tool, you could use default certificates provided by the server which you can find referenced in the `default-ssl.conf` file at `/etc/apache2/sites-available/`.
Save and close the config file.
Now we'll need to link the file we just created to the folder that Apache HTTP Server reads configurations for active sites from.
```bash
sudo mkdir /etc/apache2/sites-enabled
sudo ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/
```
In the above `ln` command, replace `example.com` with the hostname of your GoToSocial server.
Now check for configuration errors.
```bash
sudo apachectl -t
```
If everything is fine you should get this as output:
```text
Syntax OK
```
Everything working? Great! Then restart Apache HTTP Server to load your new config file.
```bash
sudo systemctl restart apache2
```
## Troubleshooting
If you cannot connect to the site in your browser, the reverse proxy setup doesn't work. Compare the Apache log file (`tail -F /var/log/apache2/access.log`) with the GoToSocial log file. Requests made must show up in both places. Double check the `ProxyPass` setting.
If you can connect but your posts don't federate and your account cannot be found from elsewhere, check your logs. Federation is broken if you see messages attempting to read your profile (something like `level=INFO … method=GET statusCode=401 path=/users/your_username msg="Unauthorized: …"`) or post to your inbox (something like `level=INFO … method=POST statusCode=404 path=/your_username/inbox msg="Not Found: …"`). Double check the `ProxyPreserveHost` setting.
If you can connect but you cannot authorize your account in a Mastodon client app, check your headers. Use `curl -I https://example.com` and look for the `Content-Security-Policy` header. If your webserver sets it, you might have to unset it. One way to do that is to use `Header unset Content-Security-Policy` in the Apache site config file (something like `example.com.conf`).

View file

@ -1,4 +1,4 @@
# Reverse proxy with Caddy 2
# Caddy 2
## Requirements
@ -49,6 +49,8 @@ In your GoToSocial config turn off Lets Encrypt by setting `letsencrypt-enabled`
If you we running GoToSocial on port 443, change the `port` value back to the default `8080`.
If the reverse proxy will be running on the same machine, set the `bind-address` to `"localhost"` so that the GoToSocial server is only accessible via loopback. Otherwise it may be possible to bypass your proxy by connecting to GoToSocial directly, which might be undesirable.
## Set up Caddy
We will configure Caddy 2 to use GoToSocial on our main domain example.org. Since Caddy takes care of obtaining the Lets Encrypt certificate, we only need to configure it properly once.
@ -77,7 +79,7 @@ example.org {
}
```
By default, caddy sets `X-Forwarded-For` in forwarded requests. To make this and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../api/ratelimiting.md) and [general configuration](../configuration/general.md) docs
By default, caddy sets `X-Forwarded-For` in forwarded requests. To make this and rate limiting work, set the `trusted-proxies` configuration variable. See the [rate limiting](../../api/ratelimiting.md) and [general configuration](../../configuration/general.md) docs
For advanced configuration check the [reverse_proxy directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy) at the Caddy documentation.

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