From 298abc4d24536510ccaa9ee80ccf431d7b867ef1 Mon Sep 17 00:00:00 2001 From: okxlin Date: Sun, 27 Aug 2023 01:18:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0element-web=E5=88=B0?= =?UTF-8?q?=E5=88=97=E8=A1=A8(=E6=84=9F=E8=B0=A2=E7=BD=91=E5=8F=8B?= =?UTF-8?q?=E5=8C=85=E5=AD=90=E5=8F=94=E7=9A=84=E6=8A=95=E7=A8=BF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/element-web/1.11.39/.env.sample | 2 + apps/element-web/1.11.39/data.yml | 10 + apps/element-web/1.11.39/docker-compose.yml | 16 + apps/element-web/README.md | 397 ++++++++++++++++++++ apps/element-web/data.yml | 20 + apps/element-web/latest/.env.sample | 2 + apps/element-web/latest/data.yml | 10 + apps/element-web/latest/docker-compose.yml | 16 + apps/element-web/logo.png | Bin 0 -> 7881 bytes 9 files changed, 473 insertions(+) create mode 100644 apps/element-web/1.11.39/.env.sample create mode 100644 apps/element-web/1.11.39/data.yml create mode 100644 apps/element-web/1.11.39/docker-compose.yml create mode 100644 apps/element-web/README.md create mode 100644 apps/element-web/data.yml create mode 100644 apps/element-web/latest/.env.sample create mode 100644 apps/element-web/latest/data.yml create mode 100644 apps/element-web/latest/docker-compose.yml create mode 100644 apps/element-web/logo.png diff --git a/apps/element-web/1.11.39/.env.sample b/apps/element-web/1.11.39/.env.sample new file mode 100644 index 00000000..a884f75c --- /dev/null +++ b/apps/element-web/1.11.39/.env.sample @@ -0,0 +1,2 @@ +CONTAINER_NAME="element-web" +PANEL_APP_PORT_HTTP="40124" diff --git a/apps/element-web/1.11.39/data.yml b/apps/element-web/1.11.39/data.yml new file mode 100644 index 00000000..a45ec47c --- /dev/null +++ b/apps/element-web/1.11.39/data.yml @@ -0,0 +1,10 @@ +additionalProperties: + formFields: + - default: 40124 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number diff --git a/apps/element-web/1.11.39/docker-compose.yml b/apps/element-web/1.11.39/docker-compose.yml new file mode 100644 index 00000000..adf19447 --- /dev/null +++ b/apps/element-web/1.11.39/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3' +services: + element-web: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:80" + image: vectorim/element-web:v1.11.39 + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/element-web/README.md b/apps/element-web/README.md new file mode 100644 index 00000000..52210e27 --- /dev/null +++ b/apps/element-web/README.md @@ -0,0 +1,397 @@ +[![Chat](https://img.shields.io/matrix/element-web:matrix.org?logo=matrix)](https://matrix.to/#/#element-web:matrix.org) +![Tests](https://github.com/vector-im/element-web/actions/workflows/tests.yaml/badge.svg) +![Static Analysis](https://github.com/vector-im/element-web/actions/workflows/static_analysis.yaml/badge.svg) +[![Weblate](https://translate.element.io/widgets/element-web/-/element-web/svg-badge.svg)](https://translate.element.io/engage/element-web/) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=element-web) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=coverage)](https://sonarcloud.io/summary/new_code?id=element-web) +[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-web) +[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-web) + +# Element + +Element (formerly known as Vector and Riot) is a Matrix web client built using the [Matrix +React SDK](https://github.com/matrix-org/matrix-react-sdk). + +# Supported Environments + +Element has several tiers of support for different environments: + +- Supported + - Definition: Issues **actively triaged**, regressions **block** the release + - Last 2 major versions of Chrome, Firefox, and Edge on desktop OSes + - Last 2 versions of Safari + - Latest release of official Element Desktop app on desktop OSes + - Desktop OSes means macOS, Windows, and Linux versions for desktop devices + that are actively supported by the OS vendor and receive security updates +- Experimental + - Definition: Issues **accepted**, regressions **do not block** the release + - Element as an installed PWA via current stable version of Chrome + - Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS +- Not supported + - Definition: Issues only affecting unsupported environments are **closed** + - Everything else + +For accessing Element on an Android or iOS device, we currently recommend the +native apps [element-android](https://github.com/vector-im/element-android) +and [element-ios](https://github.com/vector-im/element-ios). + +# Getting Started + +The easiest way to test Element is to just use the hosted copy at . +The `develop` branch is continuously deployed to +for those who like living dangerously. + +To host your own copy of Element, the quickest bet is to use a pre-built +released version of Element: + +1. Download the latest version from +1. Untar the tarball on your web server +1. Move (or symlink) the `element-x.x.x` directory to an appropriate name +1. Configure the correct caching headers in your webserver (see below) +1. Configure the app by copying `config.sample.json` to `config.json` and + modifying it. See the [configuration docs](https://github.com/vector-im/element-web/blob/develop/docs/config.md) for details. +1. Enter the URL into your browser and log into Element! + +Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located +at . + +Note that for the security of your chats will need to serve Element +over HTTPS. Major browsers also do not allow you to use VoIP/video +chats over HTTP, as WebRTC is only usable over HTTPS. +There are some exceptions like when using localhost, which is +considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts) +and thus allowed. + +To install Element as a desktop application, see [Running as a desktop +app](#running-as-a-desktop-app) below. + +# Important Security Notes + +## Separate domains + +We do not recommend running Element from the same domain name as your Matrix +homeserver. The reason is the risk of XSS (cross-site-scripting) +vulnerabilities that could occur if someone caused Element to load and render +malicious user generated content from a Matrix API which then had trusted +access to Element (or other apps) due to sharing the same domain. + +We have put some coarse mitigations into place to try to protect against this +situation, but it's still not good practice to do it in the first place. See + for more details. + +## Configuration best practices + +Unless you have special requirements, you will want to add the following to +your web server configuration when hosting Element Web: + +- The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being + framed and protect from [clickjacking][owasp-clickjacking]. +- The `frame-ancestors 'self'` directive to your `Content-Security-Policy` + header, as the modern replacement for `X-Frame-Options` (though both should be + included since not all browsers support it yet, see + [this][owasp-clickjacking-csp]). +- The `X-Content-Type-Options: nosniff` header, to [disable MIME + sniffing][mime-sniffing]. +- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in + legacy browsers. + +[mime-sniffing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing +[owasp-clickjacking-csp]: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html#content-security-policy-frame-ancestors-examples +[owasp-clickjacking]: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html + +If you are using nginx, this would look something like the following: + +``` +add_header X-Frame-Options SAMEORIGIN; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; +add_header Content-Security-Policy "frame-ancestors 'self'"; +``` + +For Apache, the configuration looks like: + +``` +Header set X-Frame-Options SAMEORIGIN +Header set X-Content-Type-Options nosniff +Header set X-XSS-Protection "1; mode=block" +Header set Content-Security-Policy "frame-ancestors 'self'" +``` + +Note: In case you are already setting a `Content-Security-Policy` header +elsewhere, you should modify it to include the `frame-ancestors` directive +instead of adding that last line. + +# Building From Source + +Element is a modular webapp built with modern ES6 and uses a Node.js build system. +Ensure you have the latest LTS version of Node.js installed. + +Using `yarn` instead of `npm` is recommended. Please see the Yarn [install +guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it already. + +1. Install or update `node.js` so that your `node` is at least the current recommended LTS. +1. Install `yarn` if not present already. +1. Clone the repo: `git clone https://github.com/vector-im/element-web.git`. +1. Switch to the element-web directory: `cd element-web`. +1. Install the prerequisites: `yarn install`. + - If you're using the `develop` branch, then it is recommended to set up a + proper development environment (see [Setting up a dev + environment](#setting-up-a-dev-environment) below). Alternatively, you + can use - the continuous integration release of + the develop branch. +1. Configure the app by copying `config.sample.json` to `config.json` and + modifying it. See the [configuration docs](https://github.com/vector-im/element-web/blob/develop/docs/config.md) for details. +1. `yarn dist` to build a tarball to deploy. Untaring this file will give + a version-specific directory containing all the files that need to go on your + web server. + +Note that `yarn dist` is not supported on Windows, so Windows users can run `yarn build`, +which will build all the necessary files into the `webapp` directory. The version of Element +will not appear in Settings without using the dist script. You can then mount the +`webapp` directory on your web server to actually serve up the app, which is +entirely static content. + +# Running as a Desktop app + +Element can also be run as a desktop app, wrapped in Electron. You can download a +pre-built version from or, if you prefer, +build it yourself. + +To build it yourself, follow the instructions at . + +Many thanks to @aviraldg for the initial work on the Electron integration. + +Other options for running as a desktop app: + +- @asdf:matrix.org points out that you can use nativefier and it just works(tm) + +```bash +yarn global add nativefier +nativefier https://app.element.io/ +``` + +The [configuration docs](https://github.com/vector-im/element-web/blob/develop/docs/config.md#desktop-app-configuration) show how to +override the desktop app's default settings if desired. + +# Running from Docker + +The Docker image can be used to serve element-web as a web server. The easiest way to use +it is to use the prebuilt image: + +```bash +docker run -p 80:80 vectorim/element-web +``` + +To supply your own custom `config.json`, map a volume to `/app/config.json`. For example, +if your custom config was located at `/etc/element-web/config.json` then your Docker command +would be: + +```bash +docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web +``` + +To build the image yourself: + +```bash +git clone https://github.com/vector-im/element-web.git element-web +cd element-web +git checkout master +docker build . +``` + +If you're building a custom branch, or want to use the develop branch, check out the appropriate +element-web branch and then run: + +```bash +docker build -t \ + --build-arg USE_CUSTOM_SDKS=true \ + --build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \ + --build-arg REACT_SDK_BRANCH="develop" \ + --build-arg JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git" \ + --build-arg JS_SDK_BRANCH="develop" \ + . +``` + +# Running in Kubernetes + +The provided element-web docker image can also be run from within a Kubernetes cluster. +See the [Kubernetes example](https://github.com/vector-im/element-web/blob/develop/docs/kubernetes.md) for more details. + +# config.json + +Element supports a variety of settings to configure default servers, behaviour, themes, etc. +See the [configuration docs](https://github.com/vector-im/element-web/blob/develop/docs/config.md) for more details. + +# Labs Features + +Some features of Element may be enabled by flags in the `Labs` section of the settings. +Some of these features are described in [labs.md](https://github.com/vector-im/element-web/blob/develop/docs/labs.md). + +# Caching requirements + +Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver: + +``` +/config.*.json +/i18n +/home +/sites +/index.html +``` + +We also recommend that you force browsers to re-validate any cached copy of Element on page load by configuring your +webserver to return `Cache-Control: no-cache` for `/`. This ensures the browser will fetch a new version of Element on +the next page load after it's been deployed. Note that this is already configured for you in the nginx config of our +Dockerfile. + +# Development + +Before attempting to develop on Element you **must** read the [developer guide +for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk#developer-guide), which +also defines the design, architecture and style for Element too. + +Read the [Choosing an issue](https://github.com/vector-im/element-web/blob/develop/docs/choosing-an-issue.md) page for some guidance +about where to start. Before starting work on a feature, it's best to ensure +your plan aligns well with our vision for Element. Please chat with the team in +[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before +you start so we can ensure it's something we'd be willing to merge. + +You should also familiarise yourself with the ["Here be Dragons" guide +](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM) +to the tame & not-so-tame dragons (gotchas) which exist in the codebase. + +The idea of Element is to be a relatively lightweight "skin" of customisations on +top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the +higher and lower level React components useful for building Matrix communication +apps using React. + +Please note that Element is intended to run correctly without access to the public +internet. So please don't depend on resources (JS libs, CSS, images, fonts) +hosted by external CDNs or servers but instead please package all dependencies +into Element itself. + +CSS hot-reload is available as an opt-in development feature. You can enable it +by defining a `CSS_HOT_RELOAD` environment variable, in a `.env` file in the root +of the repository. See `.env.example` for documentation and an example. + +# Setting up a dev environment + +Much of the functionality in Element is actually in the `matrix-react-sdk` and +`matrix-js-sdk` modules. It is possible to set these up in a way that makes it +easy to track the `develop` branches in git and to make local changes without +having to manually rebuild each time. + +First clone and build `matrix-js-sdk`: + +```bash +git clone https://github.com/matrix-org/matrix-js-sdk.git +pushd matrix-js-sdk +yarn link +yarn install +popd +``` + +Then similarly with `matrix-react-sdk`: + +```bash +git clone https://github.com/matrix-org/matrix-react-sdk.git +pushd matrix-react-sdk +yarn link +yarn link matrix-js-sdk +yarn install +popd +``` + +Clone the repo and switch to the `element-web` directory: + +```bash +git clone https://github.com/vector-im/element-web.git +cd element-web +``` + +Configure the app by copying `config.sample.json` to `config.json` and +modifying it. See the [configuration docs](https://github.com/vector-im/element-web/blob/develop/docs/config.md) for details. + +Finally, build and start Element itself: + +```bash +yarn link matrix-js-sdk +yarn link matrix-react-sdk +yarn install +yarn start +``` + +Wait a few seconds for the initial build to finish; you should see something like: + +``` +[element-js] [webpack.Progress] 100% +[element-js] +[element-js] ℹ 「wdm」: 1840 modules +[element-js] ℹ 「wdm」: Compiled successfully. +``` + +Remember, the command will not terminate since it runs the web server +and rebuilds source files when they change. This development server also +disables caching, so do NOT use it in production. + +Open in your browser to see your newly built Element. + +**Note**: The build script uses inotify by default on Linux to monitor directories +for changes. If the inotify limits are too low your build will fail silently or with +`Error: EMFILE: too many open files`. To avoid these issues, we recommend a watch limit +of at least `128M` and instance limit around `512`. + +You may be interested in issues [#15750](https://github.com/vector-im/element-web/issues/15750) and +[#15774](https://github.com/vector-im/element-web/issues/15774) for further details. + +To set a new inotify watch and instance limit, execute: + +``` +sudo sysctl fs.inotify.max_user_watches=131072 +sudo sysctl fs.inotify.max_user_instances=512 +sudo sysctl -p +``` + +If you wish, you can make the new limits permanent, by executing: + +``` +echo fs.inotify.max_user_watches=131072 | sudo tee -a /etc/sysctl.conf +echo fs.inotify.max_user_instances=512 | sudo tee -a /etc/sysctl.conf +sudo sysctl -p +``` + +--- + +When you make changes to `matrix-react-sdk` or `matrix-js-sdk` they should be +automatically picked up by webpack and built. + +If any of these steps error with, `file table overflow`, you are probably on a mac +which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again. +You'll need to do this in each new terminal you open before building Element. + +## Running the tests + +There are a number of application-level tests in the `tests` directory; these +are designed to run with Jest and JSDOM. To run them + +``` +yarn test +``` + +### End-to-End tests + +See [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/#end-to-end-tests) for how to run the end-to-end tests. + +# Translations + +To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md). + +For a developer guide, see the [translating dev doc](https://github.com/vector-im/element-web/blob/develop/docs/translating-dev.md). + +[translationsstatus](https://translate.element.io/engage/element-web/?utm_source=widget) + +# Triaging issues + +Issues are triaged by community members and the Web App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process). + +We use [issue labels](https://github.com/vector-im/element-meta/wiki/Issue-labelling) to sort all incoming issues. \ No newline at end of file diff --git a/apps/element-web/data.yml b/apps/element-web/data.yml new file mode 100644 index 00000000..238eb4f6 --- /dev/null +++ b/apps/element-web/data.yml @@ -0,0 +1,20 @@ +name: Element Web +tags: + - 工具 +title: 一款围绕您构建的安全通信平台 +type: 工具 +description: 一款围绕您构建的安全通信平台 +additionalProperties: + key: element-web + name: Element Web + tags: + - Tool + shortDescZh: 一款围绕您构建的安全通信平台 + shortDescEn: A secure communications platform built around you + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://element.io + github: https://github.com/vector-im/element-web + document: https://github.com/vector-im/element-web diff --git a/apps/element-web/latest/.env.sample b/apps/element-web/latest/.env.sample new file mode 100644 index 00000000..a884f75c --- /dev/null +++ b/apps/element-web/latest/.env.sample @@ -0,0 +1,2 @@ +CONTAINER_NAME="element-web" +PANEL_APP_PORT_HTTP="40124" diff --git a/apps/element-web/latest/data.yml b/apps/element-web/latest/data.yml new file mode 100644 index 00000000..a45ec47c --- /dev/null +++ b/apps/element-web/latest/data.yml @@ -0,0 +1,10 @@ +additionalProperties: + formFields: + - default: 40124 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number diff --git a/apps/element-web/latest/docker-compose.yml b/apps/element-web/latest/docker-compose.yml new file mode 100644 index 00000000..49628375 --- /dev/null +++ b/apps/element-web/latest/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3' +services: + element-web: + container_name: ${CONTAINER_NAME} + restart: always + networks: + - 1panel-network + ports: + - "${PANEL_APP_PORT_HTTP}:80" + image: vectorim/element-web:latest + labels: + createdBy: "Apps" + +networks: + 1panel-network: + external: true diff --git a/apps/element-web/logo.png b/apps/element-web/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..55ead7a1d3c00b3a12598957026cbf4aff9e0982 GIT binary patch literal 7881 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 ZDe1-5*Vp(=FTH6bB?UG4YKUpb{{e