| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
| |
Instead of mixing them with user authentication methods.
|
| |
|
|
|
|
|
| |
Previously m.child.room events in non-space rooms would be
treated as part of the room graph, but this is no longer
supported.
|
|
|
|
|
|
|
|
|
|
| |
This implements refresh tokens, as defined by MSC2918
This MSC has been implemented client side in Hydrogen Web: vector-im/hydrogen-web#235
The basics of the MSC works: requesting refresh tokens on login, having the access tokens expire, and using the refresh token to get a new one.
Signed-off-by: Quentin Gliech <quentingliech@gmail.com>
|
|
|
| |
Work on https://github.com/matrix-org/matrix-doc/pull/2716
|
|
|
| |
Adds a "type" field and generalize "space" to "room_id".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Trace event persistence
When we persist a batch of events, set the parent opentracing span to the that
from the request, so that we can trace all the way in.
* changelog
* When we force tracing, set a baggage item
... so that we can check again later.
* Link in both directions between persist_events spans
|
|
|
|
| |
The stable prefixes have been supported since v1.34.0. The unstable
prefixes are not supported by any known clients.
|
|
|
|
|
|
|
| |
endpoints. (#10167)
* Room version 7 for knocking.
* Stable prefixes and endpoints (both client and federation) for knocking.
* Removes the experimental configuration flag.
|
|
|
|
|
|
| |
This PR aims to implement the knock feature as proposed in https://github.com/matrix-org/matrix-doc/pull/2403
Signed-off-by: Sorunome mail@sorunome.de
Signed-off-by: Andrew Morgan andrewm@element.io
|
|
|
| |
... because tags on spans which aren't being sampled get thrown away.
|
|
|
|
| |
In lieu of just always enabling the unstable spaces endpoint and
unstable room version.
|
|
|
|
|
| |
Add a config option which allows enabling opentracing by user id, eg for
debugging requests made by a test user.
|
|
|
|
|
| |
* Correctly ratelimit invites when creating a room
Also allow ratelimiting for more than one action at a time.
|
|
|
| |
fixes #9960
|
| |
|
|
|
|
| |
Support both the unstable and stable identifiers. A future release
will disable the unstable identifiers.
|
|
|
|
|
|
| |
* Simplify `start_listening` callpath
* Correctly check the size of uploaded files
|
| |
|
|
|
|
|
|
| |
When receiving a /send_join request for a room with join rules set to 'restricted',
check if the user is a member of the spaces defined in the 'allow' key of the join rules.
This only applies to an experimental room version, as defined in MSC3083.
|
|
|
|
|
| |
hitting an 'Invalid Token' page #74" from synapse-dinsic (#9832)
This attempts to be a direct port of https://github.com/matrix-org/synapse-dinsic/pull/74 to mainline. There was some fiddling required to deal with the changes that have been made to mainline since (mainly dealing with the split of `RegistrationWorkerStore` from `RegistrationStore`, and the changes made to `self.make_request` in test code).
|
|
|
|
|
|
|
| |
Part of #9744
Removes all redundant `# -*- coding: utf-8 -*-` lines from files, as python 3 automatically reads source code as utf-8 now.
`Signed-off-by: Jonathan de Jong <jonathan@automatia.nl>`
|
|
|
| |
This change ensures that the appservice registration behaviour follows the spec. We decided to do this for Dendrite, so it made sense to also make a PR for synapse to correct the behaviour.
|
|
|
| |
Per MSC3083.
|
|
|
|
|
|
|
| |
This should fix a class of bug where we forget to check if e.g. the appservice shouldn't be ratelimited.
We also check the `ratelimit_override` table to check if the user has ratelimiting disabled. That table is really only meant to override the event sender ratelimiting, so we don't use any values from it (as they might not make sense for different rate limits), but we do infer that if ratelimiting is disabled for the user we should disabled all ratelimits.
Fixes #9663
|
|
|
|
|
|
|
|
|
| |
Running `dmypy run` will do a `mypy` check while spinning up a daemon
that makes rerunning `dmypy run` a lot faster.
`dmypy` doesn't support `follow_imports = silent` and has
`local_partial_types` enabled, so this PR enables those options and
fixes the issues that were newly raised. Note that `local_partial_types`
will be enabled by default in upcoming mypy releases.
|
|\ |
|
| |
| |
| | |
This is very bare-bones for now: federation will come soon, while pagination is descoped for now but will come later.
|
|/ |
|
| |
|
|
|
| |
This great big stack of commits is a a whole load of hoop-jumping to make it easier to store additional values in login tokens, and then to actually store the SSO Identity Provider in the login token. (Making use of that data will follow in a subsequent PR.)
|
| |
|
| |
|
|
|
|
|
|
|
| |
- Update black version to the latest
- Run black auto formatting over the codebase
- Run autoformatting according to [`docs/code_style.md
`](https://github.com/matrix-org/synapse/blob/80d6dc9783aa80886a133756028984dbf8920168/docs/code_style.md)
- Update `code_style.md` docs around installing black to use the correct version
|
|
|
|
| |
This breaks some people's configurations (if their Client-Server API
is not accessed via port 443).
|
| |
|
|
|
| |
Homeserver.get_ip_from_request() used to be a bit more complicated, but now it is totally redundant. Let's get rid of it.
|
|
|
|
|
|
|
|
|
|
|
| |
SynapseRequest is in danger of becoming a bit of a dumping-ground for "useful stuff relating to Requests",
which isn't really its intention (its purpose is to override render, finished and connectionLost to set up the
LoggingContext and write the right entries to the request log).
Putting utility functions inside SynapseRequest means that lots of our code ends up requiring a
SynapseRequest when there is nothing synapse-specific about the Request at all, and any old
twisted.web.iweb.IRequest will do. This increases code coupling and makes testing more difficult.
In short: move get_user_agent out to a utility function.
|
|
|
|
| |
An experimental room version ("org.matrix.msc2176") contains
the new redaction rules for testing.
|
|\ |
|
| | |
|
| |
| |
| |
| | |
If we see stale extremities while persisting events, and notice that
they don't change the result of state resolution, we drop them.
|
| | |
|
|/
|
|
| |
Fixes #8846.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
another user. (#8616)
We do it this way round so that only the "owner" can delete the access token (i.e. `/logout/all` by the "owner" also deletes that token, but `/logout/all` by the "target user" doesn't).
A future PR will add an API for creating such a token.
When the target user and authenticated entity are different the `Processed request` log line will be logged with a: `{@admin:server as @bob:server} ...`. I'm not convinced by that format (especially since it adds spaces in there, making it harder to use `cut -d ' '` to chop off the start of log lines). Suggestions welcome.
|
| |
|
| |
|
|
|
|
|
| |
rather than have everything that instantiates an LruCache manage metrics
separately, have LruCache do it itself.
|
|
|
|
| |
This fixes a bug where `m.ignored_user_list` was assumed to be a dict,
leading to odd behavior for users who set it to something else.
|
| |
|
|
|
|
|
|
|
| |
This converts calls like super(Foo, self) -> super().
Generated with:
sed -i "" -Ee 's/super\([^\(]+\)/super()/g' **/*.py
|
|
|
|
|
| |
This PR adds a confirmation step to resetting your user password between clicking the link in your email and your password actually being reset.
This is to better align our password reset flow with the industry standard of requiring a confirmation from the user after email validation.
|
|
|
|
|
| |
By importing from canonicaljson the simplejson module was still being used
in some situations. After this change the std lib json is consistenty used
throughout Synapse.
|
| |
|
|
|
|
|
|
| |
Add new method ratelimiter.can_requester_do_action and ensure that appservices are exempt from being ratelimited.
Co-authored-by: Patrick Cloke <clokep@users.noreply.github.com>
Co-authored-by: Erik Johnston <erik@matrix.org>
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
| |
json. (#7836)
|
| |
|
| |
|
| |
|
|
|
| |
The CI appears to use the latest version of isort, which is a problem when isort gets a major version bump. Rather than try to pin the version, I've done the necessary to make isort5 happy with synapse.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
Fixes https://github.com/matrix-org/synapse/issues/2431
Adds config option `encryption_enabled_by_default_for_room_type`, which determines whether encryption should be enabled with the default encryption algorithm in private or public rooms upon creation. Whether the room is private or public is decided based upon the room creation preset that is used.
Part of this PR is also pulling out all of the individual instances of `m.megolm.v1.aes-sha2` into a constant variable to eliminate typos ala https://github.com/matrix-org/synapse/pull/7637
Based on #7637
|
| |
|
|
|
| |
These things don't return Deferreds.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
While working on https://github.com/matrix-org/synapse/issues/5665 I found myself digging into the `Ratelimiter` class and seeing that it was both:
* Rather undocumented, and
* causing a *lot* of config checks
This PR attempts to refactor and comment the `Ratelimiter` class, as well as encourage config file accesses to only be done at instantiation.
Best to be reviewed commit-by-commit.
|
| |
|
| |
|
|
|
|
| |
In a new room version, the "notifications" key of power level events are
subject to restricted auth rules.
|
| |
|
|
|
|
| |
variables (#6391)
|
| |
|
| |
|
|
|
|
|
|
|
| |
Long story short: if we're handling presence on the current worker, we shouldn't be sending USER_SYNC commands over replication.
In an attempt to figure out what is going on here, I ended up refactoring some bits of the presencehandler code, so the first 4 commits here are non-functional refactors to move this code slightly closer to sanity. (There's still plenty to do here :/). Suggest reviewing individual commits.
Fixes (I hope) #7257.
|
| |
|
| |
|
| |
|
|
|
|
| |
room ver. (#7037)
|
| |
|
| |
|
|
|
|
| |
canonical aliases.
|
|
|
|
|
|
|
| |
... and set it everywhere it's called.
while we're here, rename it for consistency with `check_user_in_room` (and to
help check that I haven't missed any instances)
|
|
|
|
|
| |
these were getting a bit unwieldy, so let's combine `check_joined_room` and
`check_user_was_in_room` into a single `check_user_in_room`.
|
|
|
|
|
|
|
|
| |
We were looking at the wrong event type (`m.room.encryption` vs
`m.room.encrypted`).
Also fixup the duplicate `EvenTypes` entries.
Introduced in #6776.
|
|
|
|
| |
So that we can start factoring out some of this boilerplatey boilerplate.
|
| |
|
|
|
|
|
|
|
| |
These are easier to work with than the strings and we normally have one around.
This fixes `FederationHander._persist_auth_tree` which was passing a
RoomVersion object into event_auth.check instead of a string.
|
| |
|
| |
|
|
|
|
|
| |
Allow REST endpoint implemnentations to raise a RedirectException, which will
redirect the user's browser to a given location.
|
|
|
| |
This is pretty pointless. Let's just use SynapseError.
|
|
|
|
|
|
| |
This looks like it got half-killed back in #888.
Fixes #6567.
|
| |
|
|
|
|
|
| |
Previously we tried to be clever and filter out some unnecessary event
IDs to keep the auth chain small, but that had some annoying
interactions with state res v2 so we stop doing that for now.
|
|\
| |
| | |
Filter state, events_before and events_after in /context requests
|
| |\ |
|
| | | |
|
| |/
|/|
| |
| |
| |
| |
| |
| | |
Implement part [MSC2228](https://github.com/matrix-org/matrix-doc/pull/2228). The parts that differ are:
* the feature is hidden behind a configuration flag (`enable_ephemeral_messages`)
* self-destruction doesn't happen for state events
* only implement support for the `m.self_destruct_after` field (not the `m.self_destruct` one)
* doesn't send synthetic redactions to clients because for this specific case we consider the clients to be able to destroy an event themselves, instead we just censor it (by pruning its JSON) in the database
|
|\ \ |
|
| |/ |
|
|/ |
|
|\
| |
| | |
Implement MSC2326 (label based filtering)
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
|/
|
| |
Replace every instance of `logger.warn` with `logger.warning` as the former is deprecated.
|
|
|
|
| |
The expected use case is to suppress MAU limiting on small instances
|
|
|
| |
This method was somewhat redundant, and confusing.
|
|\ |
|
| |\ |
|
| |\ \ |
|
| |\ \ \ |
|
| |\ \ \ \ |
|
| | | | | | |
|
| |_|_|_|/
|/| | | |
| | | | |
| | | | | |
The only possible rejection reason is AUTH_ERROR, so all of this is unreachable.
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
* type checking fixes
* changelog
|
| | | | | |
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
We don't actually care about what happens in `get_user_by_req` and
having it as a separate span means that the entity tag isn't added to
the servlet spans, making it harder to search.
|
| |_|_|/
|/| | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
This allows support users to be created even on MAU limits via
the admin API. Support users are excluded from MAU after creation,
so it makes sense to exclude them in creation - except if the
whole host is in disabled state.
Signed-off-by: Jason Robinson <jasonr@matrix.org>
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Remove all the "double return" statements which were a result of us removing all the instances of
```
defer.returnValue(...)
return
```
statements when we switched to python3 fully.
|
| |_|/
|/| |
| | |
| | |
| | | |
Python will return a tuple whether there are parentheses around the returned values or not.
I'm just sick of my editor complaining about this all over the place :)
|
| | | |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Add authenticated_entity and servlet_names tags.
Functionally:
- Add a tag for authenticated_entity
- Add a tag for servlet_names
Stylistically:
Moved to importing methods directly from opentracing.
|
| |/
|/|
| |
| |
| | |
This is intended as an amendment to #5674 as using M_UNKNOWN as the errcode makes it hard for clients to differentiate between an invalid password and a deactivated user (the problem we were trying to solve in the first place).
M_UNKNOWN was originally chosen as it was presumed than an MSC would have to be carried out to add a new code, but as Synapse often is the testing bed for new MSC implementations, it makes sense to try it out first in the wild and then add it into the spec if it is successful. Thus this PR return a new M_USER_DEACTIVATED code when a deactivated user attempts to login.
|
| |
| |
| |
| |
| |
| |
| |
| | |
The `expire_access_token` didn't do what it sounded like it should do. What it
actually did was make Synapse enforce the 'time' caveat on macaroons used as
access tokens, but since our access token macaroons never contained such a
caveat, it was always a no-op.
(The code to add 'time' caveats was removed back in v0.18.5, in #1656)
|
|/ |
|
| |
|
|
|
|
|
| |
(#5674)
Return `This account has been deactivated` instead of `Invalid password` when a user is deactivated.
|
|
|
|
| |
Record how long an access token is valid for, and raise a soft-logout once it
expires.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
First of all, let's get rid of `TOKEN_NOT_FOUND_HTTP_STATUS`. It was a hack we
did at one point when it was possible to return either a 403 or a 401 if the
creds were missing. We always return a 401 in these cases now (thankfully), so
it's not needed.
Let's also stop abusing `AuthError` for these cases. Honestly they have nothing
that relates them to the other places that `AuthError` is used, other than the
fact that they are loosely under the 'Auth' banner. It makes no sense for them
to share exception classes.
Instead, let's add a couple of new exception classes: `InvalidClientTokenError`
and `MissingClientTokenError`, for the `M_UNKNOWN_TOKEN` and `M_MISSING_TOKEN`
cases respectively - and an `InvalidClientCredentialsError` base class for the
two of them.
|
| |
|
|\
| |
| |
| |
| | |
matrix-org/babolivier/account_validity_send_mail_auth
Don't check whether the user's account is expired on /send_mail requests
|
| | |
|
| | |
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
identity server (#5377)
Sends password reset emails from the homeserver instead of proxying to the identity server. This is now the default behaviour for security reasons. If you wish to continue proxying password reset requests to the identity server you must now enable the email.trust_identity_server_for_password_resets option.
This PR is a culmination of 3 smaller PRs which have each been separately reviewed:
* #5308
* #5345
* #5368
|
| |
| |
| |
| |
| | |
Implements [MSC2077](https://github.com/matrix-org/matrix-doc/pull/2077) and
fixes #5247 and #4364.
|
| | |
|
| | |
|
| |
| |
| |
| |
| | |
Replaces DEFAULT_ROOM_VERSION constant with a method that first checks the config, then returns a hardcoded value if the option is not present.
That hardcoded value is now located in the server.py config file.
|
| | |
|
| |
| |
| | |
Implements https://github.com/matrix-org/matrix-doc/pull/2002.
|
| |
| |
| |
| |
| |
| |
| | |
If we remove support for a particular room version, we should behave more
gracefully. This should make client requests fail with a 400 rather than a 500,
and will ignore individiual PDUs in a federation transaction, rather than the
whole transaction.
|
| |
| |
| | |
Implements MSC1884
|
| | |
|
|\ \
| | |
| | | |
Land basic reaction and edit support.
|
| | | |
|
| |/
|/| |
|
|/ |
|
|
|
|
|
| |
Follow-up to #5124
Also added a bunch of checks to make sure everything (both the stuff added on #5124 and this PR) works as intended.
|
|
|
|
| |
Rather than copying-and-pasting the same four lines hundreds of times
|
|\
| |
| |
| | |
babolivier/account_expiration
|
| |\
| | |
| | | |
Send out emails with links to extend an account's validity period
|
| | | |
|
| |\ \
| | | |
| | | | |
Add time-based account expiration
|
| | | |
| | | |
| | | | |
Transfers the m.room.related_groups state event on room upgrade.
|
| | | |
| | | |
| | | |
| | | | |
Collect all the things that make room-versions different to one another into
one place, so that it's easier to define new room versions.
|
| |_|/
|/| | |
|
| |/
|/| |
|
|/ |
|
|
|
|
|
| |
Adds a new method, check_3pid_auth, which gives password providers
the chance to allow authentication with third-party identifiers such
as email or msisdn.
|
|
|
|
|
| |
Fixes a bug where hs_disabled_message was not enforced for 3pid-based requests
if there was no server_notices_mxid configured.
|
|
|
| |
Add two ratelimiters on login (per-IP address and per-userID).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Rate-limiting for registration
* Add unit test for registration rate limiting
* Add config parameters for rate limiting on auth endpoints
* Doc
* Fix doc of rate limiting function
Co-Authored-By: babolivier <contact@brendanabolivier.com>
* Incorporate review
* Fix config parsing
* Fix linting errors
* Set default config for auth rate limiting
* Fix tests
* Add changelog
* Advance reactor instead of mocked clock
* Move parameters to registration specific config and give them more sensible default values
* Remove unused config options
* Don't mock the rate limiter un MAU tests
* Rename _register_with_store into register_with_store
* Make CI happy
* Remove unused import
* Update sample config
* Fix ratelimiting test for py2
* Add non-guest test
|
|\ |
|
| |
| |
| | |
remove trailing ,
|
|/
|
|
|
|
|
|
| |
* by default include m.room.encryption on invites
* fix constant
* changelog
|
|\ |
|
| | |
|
| |\
| | |
| | |
| | | |
erikj/redactions_eiah
|
| | | |
|
| | | |
|
| | |
| | |
| | |
| | |
| | | |
`.user_id` is proxed to `.sender` in FrozenEvent, so this has no
functional change
|
| | | |
|
| | | |
|
| | | |
|
| |/
| |
| |
| |
| |
| | |
We add the constant, but don't add it to the known room versions. This
lets us start adding V3 logic, but the servers will never join or create
V3 rooms
|
| | |
|
| |\
| | |
| | | |
Ability to search entire room history after upgrading room
|
| | |
| | |
| | | |
Co-Authored-By: anoadragon453 <1342360+anoadragon453@users.noreply.github.com>
|
| | | |
|
| | |
| | |
| | |
| | |
| | | |
* Create a new method for getting predecessor rooms
* Remove formatting change
|
| | |
| | |
| | |
| | | |
Signed-off-by: Andrew Morgan <andrew@amorgan.xyz>
|
| |\ \
| | | |
| | | | |
Add support for persisting event format versions
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Currently we only have the one event format version defined, but this
adds the necessary infrastructure to persist and fetch the format
versions alongside the events.
We specify the format version rather than the room version as:
1. We don't necessarily know the room version, existing events may be
either v1 or v2.
2. We'd need to be careful to prevent/handle correctly if different
events in the same room reported to be of different versions, which
sounds annoying.
|
| | | | |
|
| | | | |
|
| | | | |
|
|/ / / |
|
|/ / |
|
|\ \
| | |
| | |
| | | |
erikj/fed_v2_invite_server
|
| |\ \
| | | |
| | | | |
Add groundwork for new versions of federation APIs
|
| | |/
| |/|
| | |
| | |
| | |
| | |
| | |
| | | |
* Migrate encryption state on room upgrade
Signed-off-by: Andrew Morgan <andrew@amorgan.xyz>
* Add changelog file
|
| | | |
|
| |/
|/| |
|
|/ |
|
|\
| |
| |
| | |
Fixes #4371
|
| |\ |
|
| | | |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
* Correctly retry and back off if we get a HTTPerror response
* Refactor request sending to have better excpetions
MatrixFederationHttpClient blindly reraised exceptions to the caller
without differentiating "expected" failures (e.g. connection timeouts
etc) versus more severe problems (e.g. programming errors).
This commit adds a RequestSendFailed exception that is raised when
"expected" failures happen, allowing the TransactionQueue to log them as
warnings while allowing us to log other exceptions as actual exceptions.
|
| | |
| | |
| | |
| | |
| | |
| | | |
(#3405)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
|
|\ \ \
| | | |
| | | | |
Add v2 room version
|
| | | | |
|
| |/ /
|/| |
| | |
| | |
| | |
| | | |
Allow for the creation of a support user.
A support user can access the server, join rooms, interact with other users, but does not appear in the user directory nor does it contribute to monthly active user limits.
|
|/ / |
|
|\ \
| | |
| | | |
Add m.login.terms to the registration flow
|
| |\ \ |
|
| |\ \ \ |
|
| |\ \ \ \ |
|
| | | | | |
| | | | | |
| | | | | | |
As per https://github.com/vector-im/riot-web/issues/7168#issuecomment-419996117
|
| |_|_|/ /
|/| | | | |
|
| | | | | |
|
| |_|/ /
|/| | |
| | | |
| | | |
| | | | |
Currently just creates a new, empty, room, and sends a tombstone in the old
room.
|
| |/ /
|/| |
| | |
| | |
| | |
| | |
| | |
| | | |
Fixes a bug introduced in https://github.com/matrix-org/synapse/pull/1783 which
meant that single backslashes were not allowed in event field filters.
The intention here is to allow single-backslashes, but disallow
double-backslashes.
|
| | | |
|
| | | |
|
|\| | |
|
| | | |
|
| | |
| | |
| | |
| | | |
Signed-off-by: Schnuffle <schnuffle@github.com>
|
| | |
| | |
| | |
| | |
| | | |
This has been specced and part-implemented; let's implement it for /sync (but
no other endpoints yet :/).
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
| | | |
|
|\| | |
|
| | | |
|
| |\ \
| | | |
| | | |
| | | | |
neilj/server_notices_on_blocking
|
| | |\ \
| | | | |
| | | | | |
Refactor state module to support multiple room versions
|
| | | |\ \
| | | | | |
| | | | | |
| | | | | | |
erikj/refactor_state_handler
|
| | | | | | |
|
| | | |/ /
| | |/| | |
|
| | | | | |
|
| | | | | |
|
| | | | | |
|