Merge remote-tracking branch 'shay/shay/freeze_directory' into matrix-org-hotfixes
commit
c2deef254a
|
@ -0,0 +1,90 @@
|
|||
name: Add Version Picker (RUN ONCE)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
add-version-picker:
|
||||
name: Add Version Picker
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.email "action@synapse.bot.com"
|
||||
git config user.name "Action Bot"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup mdbook
|
||||
uses: peaceiris/actions-mdbook@adeb05db28a0c0004681db83893d56c0388ea9ea # v1.2.0
|
||||
with:
|
||||
mdbook-version: '0.4.17'
|
||||
|
||||
- name: Copy files to release branches
|
||||
run: |
|
||||
for version in "v1.98" "v1.97" "v1.96" "v1.95" "v1.94" "v1.93" "v1.92" "v1.91" "v1.90" "v1.89" "v1.88" "v1.87" "v1.86" "v1.85" "v1.84" "v1.83" "v1.82" "v1.81" "v1.80" "v1.79" "v1.78" "v1.77" "v1.76" "v1.75" "v1.74" "v1.73" "v1.72" "v1.71" "v1.70" "v1.69" "v1.68" "v1.67" "v1.66" "v1.65" "v1.64" "v1.63" "v1.62" "v1.61" "v1.60" "v1.59" "v1.58" "v1.57" "v1.56" "v1.55" "v1.54" "v1.53" "v1.52" "v1.51" "v1.50" "v1.49" "v1.48" "v1.47" "v1.46" "v1.45" "v1.44" "v1.43" "v1.42" "v1.41" "v1.40" "v1.39" "v1.38" "v1.37"
|
||||
do
|
||||
git fetch
|
||||
git checkout -b release-$version origin/release-$version
|
||||
|
||||
git checkout develop -- ./book.toml
|
||||
git checkout develop -- ./docs/website_files/version-picker.js
|
||||
git checkout develop -- ./docs/website_files/version-picker.css
|
||||
git checkout develop -- ./docs/website_files/README.md
|
||||
|
||||
echo "window.SYNAPSE_VERSION = '$version';" > ./docs/website_files/version.js
|
||||
|
||||
# Adding version-picker element to index.hbs
|
||||
awk '/<button id="search-toggle" class="icon-button" type="button" title="Search. \(Shortkey: s\)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">/{
|
||||
print; getline; print; getline; print; getline; print;
|
||||
print "\
|
||||
<div class=\"version-picker\">\n\
|
||||
<div class=\"dropdown\">\n\
|
||||
<div class=\"select\">\n\
|
||||
<span></span>\n\
|
||||
<i class=\"fa fa-chevron-down\"></i>\n\
|
||||
</div>\n\
|
||||
<input type=\"hidden\" name=\"version\">\n\
|
||||
<ul class=\"dropdown-menu\">\n\
|
||||
<!-- Versions will be added dynamically in version-picker.js -->\n\
|
||||
</ul>\n\
|
||||
</div>\n\
|
||||
</div>\
|
||||
";
|
||||
next
|
||||
} 1' ./docs/website_files/theme/index.hbs > output.html && mv output.html ./docs/website_files/theme/index.hbs
|
||||
|
||||
git add ./book.toml ./docs/website_files/version-picker.js ./docs/website_files/version-picker.css ./docs/website_files/version.js ./docs/website_files/README.md ./docs/website_files/theme/index.hbs
|
||||
git commit -m "Version picker added for $version docs"
|
||||
git push
|
||||
done
|
||||
|
||||
- name: Build docs for Github Pages
|
||||
run: |
|
||||
git fetch
|
||||
git branch gh-pages origin/gh-pages
|
||||
|
||||
for version in "v1.98" "v1.97" "v1.96" "v1.95" "v1.94" "v1.93" "v1.92" "v1.91" "v1.90" "v1.89" "v1.88" "v1.87" "v1.86" "v1.85" "v1.84" "v1.83" "v1.82" "v1.81" "v1.80" "v1.79" "v1.78" "v1.77" "v1.76" "v1.75" "v1.74" "v1.73" "v1.72" "v1.71" "v1.70" "v1.69" "v1.68" "v1.67" "v1.66" "v1.65" "v1.64" "v1.63" "v1.62" "v1.61" "v1.60" "v1.59" "v1.58" "v1.57" "v1.56" "v1.55" "v1.54" "v1.53" "v1.52" "v1.51" "v1.50" "v1.49" "v1.48" "v1.47" "v1.46" "v1.45" "v1.44" "v1.43" "v1.42" "v1.41" "v1.40" "v1.39" "v1.38" "v1.37"
|
||||
do
|
||||
git checkout release-$version
|
||||
|
||||
mdbook build && cp book/welcome_and_overview.html book/index.html
|
||||
mkdir ver-temp && cp -r book/* ver-temp/
|
||||
rm -r ./book
|
||||
|
||||
git checkout gh-pages
|
||||
rm -r $version
|
||||
mv ver-temp $version
|
||||
|
||||
git add ./$version
|
||||
git commit -m "Version picker deployed for $version docs to Github Pages"
|
||||
done
|
||||
|
||||
- name: Push to gh-pages
|
||||
run: |
|
||||
git checkout gh-pages
|
||||
git status
|
||||
git push
|
|
@ -60,6 +60,9 @@ jobs:
|
|||
with:
|
||||
mdbook-version: '0.4.17'
|
||||
|
||||
- name: Set version of docs
|
||||
run: echo 'window.SYNAPSE_VERSION = "${{ needs.pre.outputs.branch-version }}";' > ./docs/website_files/version.js
|
||||
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
|
|
|
@ -34,8 +34,13 @@ additional-css = [
|
|||
"docs/website_files/table-of-contents.css",
|
||||
"docs/website_files/remove-nav-buttons.css",
|
||||
"docs/website_files/indent-section-headers.css",
|
||||
"docs/website_files/version-picker.css",
|
||||
]
|
||||
additional-js = [
|
||||
"docs/website_files/table-of-contents.js",
|
||||
"docs/website_files/version-picker.js",
|
||||
"docs/website_files/version.js",
|
||||
]
|
||||
additional-js = ["docs/website_files/table-of-contents.js"]
|
||||
theme = "docs/website_files/theme"
|
||||
|
||||
[preprocessor.schema_versions]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Added version picker for Synapse documentation. Contributed by @Dmytro27Ind.
|
|
@ -0,0 +1 @@
|
|||
Update the implementation of [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965) (OIDC Provider discovery).
|
|
@ -0,0 +1 @@
|
|||
Clarify that `password_config.enabled: "only_for_reauth"` does not allow new logins to be created using password auth.
|
|
@ -0,0 +1 @@
|
|||
Fix a long-standing bug where the signing keys generated by Synapse were world-readable. Contributed by Fabian Klemp.
|
|
@ -495,10 +495,10 @@ Unix socket support (_Added in Synapse 1.89.0_):
|
|||
* **Note**: The use of both `path` and `port` options for the same `listener` is not
|
||||
compatible.
|
||||
* The `x_forwarded` option defaults to true when using Unix sockets and can be omitted.
|
||||
* Other options that would not make sense to use with a UNIX socket, such as
|
||||
* Other options that would not make sense to use with a UNIX socket, such as
|
||||
`bind_addresses` and `tls` will be ignored and can be removed.
|
||||
* `mode`: The file permissions to set on the UNIX socket. Defaults to `666`
|
||||
* **Note:** Must be set as `type: http` (does not support `metrics` and `manhole`).
|
||||
* **Note:** Must be set as `type: http` (does not support `metrics` and `manhole`).
|
||||
Also make sure that `metrics` is not included in `resources` -> `names`
|
||||
|
||||
|
||||
|
@ -2932,7 +2932,7 @@ access tokens via a query parameter.
|
|||
|
||||
Example configuration:
|
||||
```yaml
|
||||
use_appservice_legacy_authorization: true
|
||||
use_appservice_legacy_authorization: true
|
||||
```
|
||||
|
||||
---
|
||||
|
@ -3613,7 +3613,7 @@ This setting has the following sub-options:
|
|||
* `enabled`: Defaults to true.
|
||||
Set to false to disable password authentication.
|
||||
Set to `only_for_reauth` to allow users with existing passwords to use them
|
||||
to log in and reauthenticate, whilst preventing new users from setting passwords.
|
||||
to reauthenticate (not log in), whilst preventing new users from setting passwords.
|
||||
* `localdb_enabled`: Set to false to disable authentication against the local password
|
||||
database. This is ignored if `enabled` is false, and is only useful
|
||||
if you have other `password_providers`. Defaults to true.
|
||||
|
@ -3865,7 +3865,7 @@ This setting is an optional list of 0 or more rules. By default, no list is
|
|||
provided, meaning that all alias creations are permitted.
|
||||
|
||||
Otherwise, requests to create aliases are matched against each rule in order.
|
||||
The first rule that matches decides if the request is allowed or denied. If no
|
||||
The first rule that matches decides if the request is allowed or denied. If no
|
||||
rule matches, the request is denied. In particular, this means that configuring
|
||||
an empty list of rules will deny every alias creation request.
|
||||
|
||||
|
@ -3877,7 +3877,7 @@ Each rule is a YAML object containing four fields, each of which is an optional
|
|||
* `action`: either `allow` or `deny`. What to do with the request if the rule matches. Defaults to `allow`.
|
||||
|
||||
Each of the glob patterns is optional, defaulting to `*` ("match anything").
|
||||
Note that the patterns match against fully qualified IDs, e.g. against
|
||||
Note that the patterns match against fully qualified IDs, e.g. against
|
||||
`@alice:example.com`, `#room:example.com` and `!abcdefghijk:example.com` instead
|
||||
of `alice`, `room` and `abcedgghijk`.
|
||||
|
||||
|
@ -3914,7 +3914,7 @@ alias_creation_rules:
|
|||
alias_creation_rules:
|
||||
- user_id: "@bad_user:example.com"
|
||||
action: deny
|
||||
|
||||
|
||||
- action: allow
|
||||
```
|
||||
|
||||
|
@ -3992,7 +3992,7 @@ room_list_publication_rules:
|
|||
room_list_publication_rules:
|
||||
- user_id: "@bad_user:example.com"
|
||||
action: deny
|
||||
|
||||
|
||||
- action: allow
|
||||
```
|
||||
|
||||
|
@ -4408,7 +4408,7 @@ must be declared, in the same way as the [`listeners` option](#listeners)
|
|||
in the shared config.
|
||||
|
||||
Workers declared in [`stream_writers`](#stream_writers) and [`instance_map`](#instance_map)
|
||||
will need to include a `replication` listener here, in order to accept internal HTTP
|
||||
will need to include a `replication` listener here, in order to accept internal HTTP
|
||||
requests from other workers.
|
||||
|
||||
Example configuration:
|
||||
|
|
|
@ -24,6 +24,11 @@ Finally, we also stylise the chapter titles in the left sidebar by indenting the
|
|||
slightly so that they are more visually distinguishable from the section headers
|
||||
(the bold titles). This is done through the `indent-section-headers.css` file.
|
||||
|
||||
In addition to these modifications, we have added a version picker to the documentation.
|
||||
Users can switch between documentations for different versions of Synapse.
|
||||
This functionality was implemented through the `version-picker.js` and
|
||||
`version-picker.css` files.
|
||||
|
||||
More information can be found in mdbook's official documentation for
|
||||
[injecting page JS/CSS](https://rust-lang.github.io/mdBook/format/config.html)
|
||||
and
|
||||
|
|
|
@ -131,6 +131,18 @@
|
|||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
<div class="version-picker">
|
||||
<div class="dropdown">
|
||||
<div class="select">
|
||||
<span></span>
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</div>
|
||||
<input type="hidden" name="version">
|
||||
<ul class="dropdown-menu">
|
||||
<!-- Versions will be added dynamically in version-picker.js -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">{{ book_title }}</h1>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
.version-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.version-picker .dropdown {
|
||||
width: 130px;
|
||||
max-height: 29px;
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--theme-popup-border);
|
||||
position: relative;
|
||||
font-size: 13px;
|
||||
color: var(--fg);
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
.version-picker .dropdown .select {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: 5px 2px 5px 15px;
|
||||
}
|
||||
.version-picker .dropdown .select > i {
|
||||
font-size: 10px;
|
||||
color: var(--fg);
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
.version-picker .dropdown:hover {
|
||||
border: 1px solid var(--theme-popup-border);
|
||||
}
|
||||
.version-picker .dropdown:active {
|
||||
background-color: var(--theme-popup-bg);
|
||||
}
|
||||
.version-picker .dropdown.active:hover,
|
||||
.version-picker .dropdown.active {
|
||||
border: 1px solid var(--theme-popup-border);
|
||||
border-radius: 2px 2px 0 0;
|
||||
background-color: var(--theme-popup-bg);
|
||||
}
|
||||
.version-picker .dropdown.active .select > i {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
.version-picker .dropdown .dropdown-menu {
|
||||
position: absolute;
|
||||
background-color: var(--theme-popup-bg);
|
||||
width: 100%;
|
||||
left: -1px;
|
||||
right: 1px;
|
||||
margin-top: 1px;
|
||||
border: 1px solid var(--theme-popup-border);
|
||||
border-radius: 0 0 4px 4px;
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
z-index: 9;
|
||||
}
|
||||
.version-picker .dropdown .dropdown-menu li {
|
||||
font-size: 12px;
|
||||
padding: 6px 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.version-picker .dropdown .dropdown-menu {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.version-picker .dropdown .dropdown-menu li:hover {
|
||||
background-color: var(--theme-hover);
|
||||
}
|
||||
.version-picker .dropdown .dropdown-menu li.active::before {
|
||||
display: inline-block;
|
||||
content: "✓";
|
||||
margin-inline-start: -14px;
|
||||
width: 14px;
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
|
||||
const dropdown = document.querySelector('.version-picker .dropdown');
|
||||
const dropdownMenu = dropdown.querySelector('.dropdown-menu');
|
||||
|
||||
fetchVersions(dropdown, dropdownMenu).then(() => {
|
||||
initializeVersionDropdown(dropdown, dropdownMenu);
|
||||
});
|
||||
|
||||
/**
|
||||
* Initialize the dropdown functionality for version selection.
|
||||
*
|
||||
* @param {Element} dropdown - The dropdown element.
|
||||
* @param {Element} dropdownMenu - The dropdown menu element.
|
||||
*/
|
||||
function initializeVersionDropdown(dropdown, dropdownMenu) {
|
||||
// Toggle the dropdown menu on click
|
||||
dropdown.addEventListener('click', function () {
|
||||
this.setAttribute('tabindex', 1);
|
||||
this.classList.toggle('active');
|
||||
dropdownMenu.style.display = (dropdownMenu.style.display === 'block') ? 'none' : 'block';
|
||||
});
|
||||
|
||||
// Remove the 'active' class and hide the dropdown menu on focusout
|
||||
dropdown.addEventListener('focusout', function () {
|
||||
this.classList.remove('active');
|
||||
dropdownMenu.style.display = 'none';
|
||||
});
|
||||
|
||||
// Handle item selection within the dropdown menu
|
||||
const dropdownMenuItems = dropdownMenu.querySelectorAll('li');
|
||||
dropdownMenuItems.forEach(function (item) {
|
||||
item.addEventListener('click', function () {
|
||||
dropdownMenuItems.forEach(function (item) {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
this.classList.add('active');
|
||||
dropdown.querySelector('span').textContent = this.textContent;
|
||||
dropdown.querySelector('input').value = this.getAttribute('id');
|
||||
|
||||
window.location.href = changeVersion(window.location.href, this.textContent);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* This function fetches the available versions from a GitHub repository
|
||||
* and inserts them into the version picker.
|
||||
*
|
||||
* @param {Element} dropdown - The dropdown element.
|
||||
* @param {Element} dropdownMenu - The dropdown menu element.
|
||||
* @returns {Promise<Array<string>>} A promise that resolves with an array of available versions.
|
||||
*/
|
||||
function fetchVersions(dropdown, dropdownMenu) {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.addEventListener("load", () => {
|
||||
|
||||
fetch("https://api.github.com/repos/matrix-org/synapse/git/trees/gh-pages", {
|
||||
cache: "force-cache",
|
||||
}).then(res =>
|
||||
res.json()
|
||||
).then(resObject => {
|
||||
const excluded = ['dev-docs', 'v1.91.0', 'v1.80.0', 'v1.69.0'];
|
||||
const tree = resObject.tree.filter(item => item.type === "tree" && !excluded.includes(item.path));
|
||||
const versions = tree.map(item => item.path).sort(sortVersions);
|
||||
|
||||
// Create a list of <li> items for versions
|
||||
versions.forEach((version) => {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = version;
|
||||
li.id = version;
|
||||
|
||||
if (window.SYNAPSE_VERSION === version) {
|
||||
li.classList.add('active');
|
||||
dropdown.querySelector('span').textContent = version;
|
||||
dropdown.querySelector('input').value = version;
|
||||
}
|
||||
|
||||
dropdownMenu.appendChild(li);
|
||||
});
|
||||
|
||||
resolve(versions);
|
||||
|
||||
}).catch(ex => {
|
||||
console.error("Failed to fetch version data", ex);
|
||||
reject(ex);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom sorting function to sort an array of version strings.
|
||||
*
|
||||
* @param {string} a - The first version string to compare.
|
||||
* @param {string} b - The second version string to compare.
|
||||
* @returns {number} - A negative number if a should come before b, a positive number if b should come before a, or 0 if they are equal.
|
||||
*/
|
||||
function sortVersions(a, b) {
|
||||
// Put 'develop' and 'latest' at the top
|
||||
if (a === 'develop' || a === 'latest') return -1;
|
||||
if (b === 'develop' || b === 'latest') return 1;
|
||||
|
||||
const versionA = (a.match(/v\d+(\.\d+)+/) || [])[0];
|
||||
const versionB = (b.match(/v\d+(\.\d+)+/) || [])[0];
|
||||
|
||||
return versionB.localeCompare(versionA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the version in a URL path.
|
||||
*
|
||||
* @param {string} url - The original URL to be modified.
|
||||
* @param {string} newVersion - The new version to replace the existing version in the URL.
|
||||
* @returns {string} The updated URL with the new version.
|
||||
*/
|
||||
function changeVersion(url, newVersion) {
|
||||
const parsedURL = new URL(url);
|
||||
const pathSegments = parsedURL.pathname.split('/');
|
||||
|
||||
// Modify the version
|
||||
pathSegments[2] = newVersion;
|
||||
|
||||
// Reconstruct the URL
|
||||
parsedURL.pathname = pathSegments.join('/');
|
||||
|
||||
return parsedURL.href;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
window.SYNAPSE_VERSION = "latest";
|
|
@ -13,6 +13,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from signedjson.key import generate_signing_key, write_signing_keys
|
||||
|
@ -26,15 +27,21 @@ def main() -> None:
|
|||
parser.add_argument(
|
||||
"-o",
|
||||
"--output_file",
|
||||
type=argparse.FileType("w"),
|
||||
default=sys.stdout,
|
||||
type=str,
|
||||
default="-",
|
||||
help="Where to write the output to",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
key_id = "a_" + random_string(4)
|
||||
key = (generate_signing_key(key_id),)
|
||||
write_signing_keys(args.output_file, key)
|
||||
if args.output_file == "-":
|
||||
write_signing_keys(sys.stdout, key)
|
||||
else:
|
||||
with open(
|
||||
args.output_file, "w", opener=lambda p, f: os.open(p, f, mode=0o640)
|
||||
) as signing_key_file:
|
||||
write_signing_keys(signing_key_file, key)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -263,7 +263,9 @@ class KeyConfig(Config):
|
|||
|
||||
if not self.path_exists(signing_key_path):
|
||||
print("Generating signing key file %s" % (signing_key_path,))
|
||||
with open(signing_key_path, "w") as signing_key_file:
|
||||
with open(
|
||||
signing_key_path, "w", opener=lambda p, f: os.open(p, f, mode=0o640)
|
||||
) as signing_key_file:
|
||||
key_id = "a_" + random_string(4)
|
||||
write_signing_keys(signing_key_file, (generate_signing_key(key_id),))
|
||||
else:
|
||||
|
@ -274,7 +276,9 @@ class KeyConfig(Config):
|
|||
key = decode_signing_key_base64(
|
||||
NACL_ED25519, key_id, signing_keys.split("\n")[0]
|
||||
)
|
||||
with open(signing_key_path, "w") as signing_key_file:
|
||||
with open(
|
||||
signing_key_path, "w", opener=lambda p, f: os.open(p, f, mode=0o640)
|
||||
) as signing_key_file:
|
||||
write_signing_keys(signing_key_file, (key,))
|
||||
|
||||
|
||||
|
|
|
@ -871,7 +871,9 @@ class RoomCreationHandler:
|
|||
|
||||
# The spec says rooms should default to private visibility if
|
||||
# `visibility` is not specified.
|
||||
visibility = config.get("visibility", "private")
|
||||
#visibility = config.get("visibility", "private")
|
||||
# temporarily block publishing rooms to directory - patch date 12/12/23
|
||||
visibility = "private"
|
||||
is_public = visibility == "public"
|
||||
|
||||
self._validate_room_config(config, visibility)
|
||||
|
|
|
@ -22,6 +22,7 @@ from synapse.rest.client import (
|
|||
account_validity,
|
||||
appservice_ping,
|
||||
auth,
|
||||
auth_issuer,
|
||||
capabilities,
|
||||
devices,
|
||||
directory,
|
||||
|
@ -148,3 +149,4 @@ class ClientRestResource(JsonResource):
|
|||
mutual_rooms.register_servlets(hs, client_resource)
|
||||
login_token_request.register_servlets(hs, client_resource)
|
||||
rendezvous.register_servlets(hs, client_resource)
|
||||
auth_issuer.register_servlets(hs, client_resource)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import logging
|
||||
import typing
|
||||
from typing import Tuple
|
||||
|
||||
from synapse.api.errors import Codes, SynapseError
|
||||
from synapse.http.server import HttpServer
|
||||
from synapse.http.servlet import RestServlet
|
||||
from synapse.http.site import SynapseRequest
|
||||
from synapse.rest.client._base import client_patterns
|
||||
from synapse.types import JsonDict
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from synapse.server import HomeServer
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AuthIssuerServlet(RestServlet):
|
||||
"""
|
||||
Advertises what OpenID Connect issuer clients should use to authorise users.
|
||||
"""
|
||||
|
||||
PATTERNS = client_patterns(
|
||||
"/org.matrix.msc2965/auth_issuer$",
|
||||
unstable=True,
|
||||
releases=(),
|
||||
)
|
||||
|
||||
def __init__(self, hs: "HomeServer"):
|
||||
super().__init__()
|
||||
self._config = hs.config
|
||||
|
||||
async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
|
||||
if self._config.experimental.msc3861.enabled:
|
||||
return 200, {"issuer": self._config.experimental.msc3861.issuer}
|
||||
else:
|
||||
# Wouldn't expect this to be reached: the servelet shouldn't have been
|
||||
# registered. Still, fail gracefully if we are registered for some reason.
|
||||
raise SynapseError(
|
||||
404,
|
||||
"OIDC discovery has not been configured on this homeserver",
|
||||
Codes.NOT_FOUND,
|
||||
)
|
||||
|
||||
|
||||
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
|
||||
# We use the MSC3861 values as they are used by multiple MSCs
|
||||
if hs.config.experimental.msc3861.enabled:
|
||||
AuthIssuerServlet(hs).register(http_server)
|
|
@ -159,6 +159,16 @@ class ClientDirectoryListServer(RestServlet):
|
|||
|
||||
content = parse_and_validate_json_object_from_request(request, self.PutBody)
|
||||
|
||||
# temporarily block publishing rooms to public directory for non-admins
|
||||
# patch date 12/12/23
|
||||
if content.visibility == "public":
|
||||
is_admin = await self.is_server_admin(requester)
|
||||
if not is_admin:
|
||||
raise AuthError(
|
||||
403,
|
||||
"Publishing rooms to the room list is temporarily disabled.",
|
||||
)
|
||||
|
||||
await self.directory_handler.edit_published_room_list(
|
||||
requester, room_id, content.visibility
|
||||
)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from http import HTTPStatus
|
||||
|
||||
from synapse.rest.client import auth_issuer
|
||||
|
||||
from tests.unittest import HomeserverTestCase, override_config, skip_unless
|
||||
from tests.utils import HAS_AUTHLIB
|
||||
|
||||
ISSUER = "https://account.example.com/"
|
||||
|
||||
|
||||
class AuthIssuerTestCase(HomeserverTestCase):
|
||||
servlets = [
|
||||
auth_issuer.register_servlets,
|
||||
]
|
||||
|
||||
def test_returns_404_when_msc3861_disabled(self) -> None:
|
||||
# Make an unauthenticated request for the discovery info.
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
"/_matrix/client/unstable/org.matrix.msc2965/auth_issuer",
|
||||
)
|
||||
self.assertEqual(channel.code, HTTPStatus.NOT_FOUND)
|
||||
|
||||
@skip_unless(HAS_AUTHLIB, "requires authlib")
|
||||
@override_config(
|
||||
{
|
||||
"disable_registration": True,
|
||||
"experimental_features": {
|
||||
"msc3861": {
|
||||
"enabled": True,
|
||||
"issuer": ISSUER,
|
||||
"client_id": "David Lister",
|
||||
"client_auth_method": "client_secret_post",
|
||||
"client_secret": "Who shot Mister Burns?",
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
def test_returns_issuer_when_oidc_enabled(self) -> None:
|
||||
# Make an unauthenticated request for the discovery info.
|
||||
channel = self.make_request(
|
||||
"GET",
|
||||
"/_matrix/client/unstable/org.matrix.msc2965/auth_issuer",
|
||||
)
|
||||
self.assertEqual(channel.code, HTTPStatus.OK)
|
||||
self.assertEqual(channel.json_body, {"issuer": ISSUER})
|
Loading…
Reference in New Issue