snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "Configuration"
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
### Config module
|
||||
|
||||
The **configuration** module in the **Common** module is responsible for facilitating reading from and writing to external configuration sources. It also consolidates, verifies, and upgrades configuration where applicable.
|
||||
|
||||
#### Files
|
||||
|
||||
We have a few different configuration files in the Desktop App, but the main one is `config.json`. Most of the user's configuration from the Settings Window is stored there, as well as any user-configured servers.
|
||||
|
||||
The application supports different configuration versions and allows for them to be migrating to the version supported by the configuration module via the `upgradePreferences` module. When no configuration is found, the `defaultPreferences` object is copied over to the main configuration module.
|
||||
|
||||
We also support a build configuration in which the packager of the application can pre-define servers and a few other configuration items.
|
||||
|
||||
#### Registry
|
||||
|
||||
We support reading from the Windows registry to allow system administrators to define Group Policy that will pre-define servers and potentially disable user-defined servers and automatic updates as per administrator wishes.
|
||||
|
||||
Templates for these can be found under `resources\windows\gpo`.
|
||||
|
||||
### Server manager
|
||||
|
||||
The `ServerManager` is a singleton class that acts as a single source of truth for all server configuration, managing adding/modifying/removing servers and serving the server information to the rest of the application.
|
||||
|
||||
#### Initialization
|
||||
|
||||
We populate the `ServerManager` with all servers provided by the **configuration** module, marking them as pre-defined when applicable to not allow the user to modify them. Servers are given a unique UUID when the app initialized, and this UUID acts as the global way of identifying the server to the rest of the application.
|
||||
|
||||
An external call is responsible for populating information about the specific Mattermost server (eg. server version, plugins installed), but the data is stored within the `ServerManager`.
|
||||
|
||||
#### Modification
|
||||
|
||||
The `ServerManager` is the only place that allows the persistent server configuration to be modified. Changes cannot be made directly through the **configuration** module. Once a server is modified, the `ServerManager` will update the **configuration** module with the new changes.
|
||||
|
||||
When a server is added or updating, up to two events will be emitted:
|
||||
- `SERVERS_UPDATE`: This event is emitted when the `ServerManager` has new changes. This could be a name, URL or an ordering change.
|
||||
- `SERVERS_URL_MODIFIED`: This event is emitted specifically when a URL has changed, signifying that the application might need to fetch new remote server information or refresh any views associated with the server to reflect the new URL.
|
||||
|
||||
#### Lookup
|
||||
|
||||
We provide a server lookup call that allows for an arbitrary URL to be provided and potentially matched to a server. If found, the UUID will be provided. This function is useful for deep linking or for cross-server linking, when only a URL is available when the request is provided.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
title: "External views"
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
To provide access to different servers, we create a series of `BrowserView` objects that directly render on top of the Main Window and load the Mattermost Web App directly from the server they correspond to. We wrap these `BrowserView` objects into a `MattermostView` that manages the loading of the view and handles events such as navigation and notifications.
|
||||
|
||||
These views are also contained within and managed by the `viewManager` class. The class is responsible for adding and removing the views from the Main Window when the user needs them and handling IPC calls from the renderer processes and passing them to the child objects.
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "Architecture"
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
#### Electron
|
||||
The Desktop App, like all Electron apps, is broken into two pieces: the **main** process and the **renderer** process.
|
||||
|
||||
- The **main** process is a NodeJS process that has access to operating system functions, and governs the creation and management of several renderer processes.
|
||||
- The **renderer** processes are Chromium instances that perform different functions. In our app, each Mattermost server is its own renderer process.
|
||||
|
||||

|
||||
|
||||
In order to facilitate communication between the two processes, there's a communication layer in which information can be sent between. We expose *ONLY* the communication API to the renderer process so that we don't allow any malicious server to wreak havoc on a user's computer.
|
||||
|
||||
You can read more about the Process Model [here](https://www.electronjs.org/docs/latest/tutorial/process-model).
|
||||
|
||||
#### Directory structure
|
||||
The directory structure is broken down into a few pieces to best organize the code:
|
||||
|
||||
```
|
||||
Mattermost Desktop
|
||||
├── docs/ - Documentation for working on the Desktop App
|
||||
├── e2e/ - E2E tests
|
||||
│ ├── modules/ - Setup code for the E2E tests
|
||||
│ └── specs/ - E2E tests themselves
|
||||
├── resources/ - Assets such as images or sound files that the Desktop App uses
|
||||
├── scripts/ - Automated scripts used for building or packaging the Desktop App
|
||||
└── src/ - Application source code
|
||||
├── assets/ - Assets such as images or sound files that the Desktop App uses
|
||||
├── common/ - Common objects and utility functions that aren't specifically tied to Electron
|
||||
├── main/ - The majority of the main process code, including setup for the Electron app
|
||||
├── renderer/ - The web code for all of the main application wrapper, modals. and server dropdown views that are used by the renderer process
|
||||
└── types/ - Common types for use between all of the individual modules
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: "Internal views"
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
There are several renderer processes that make up the internal interface of the Desktop App. These are all represented by singleton objects that reside in the Main Module. These classes are in charge of holding the corresponding `BrowserWindow` or `BrowserView` object, initializing any handlers specific to that view, and exposing any special functionality that other modules may need to either read or affect the view.
|
||||
|
||||
As all of these views only load trusted scripts in the renderer process, all of these views are given full access to the `desktopAPI` module, allowing them to perform basically any action that we allow for in the Desktop App via the IPC layer.
|
||||
|
||||
### Windows
|
||||
|
||||
These are the internally-managed windows acting as the main user interface points for the user. Each of these views are represented by a `BrowserWindow` object.
|
||||
|
||||
#### Main window
|
||||
|
||||

|
||||
|
||||
This is the primary view that encapsulates the core of the Desktop App interface. Most `BrowserView` objects are rendered using this window as their parent, and are affected by the behavior of this window. Most other controls, including the tray icon and taskbar/dock icon, interact with this window, and most of their functionality is tied to it as well.
|
||||
|
||||
This window is managed by the `MainWindow` module located at [main/windows/mainWindow](https://github.com/mattermost/desktop/blob/master/src/main/windows/mainWindow.ts).
|
||||
|
||||
##### Hooks
|
||||
- `init()`: Creates the `BrowserWindow` object for the Main Window and adds all appropriate listeners.
|
||||
- `get()`: Returns the `BrowserWindow` object for the Main Window. This is directly exposed as there are many different functions affecting the behavior of the window, and thus the encapsulating module often needs to pass that control to other modules. If `true` is passed as an argument, `init()` will be called if the window does not exist, otherwise `undefined` is returned.
|
||||
- `getBounds()`: Returns the current size and location of the `BrowserWindow`, used for resize functionality, and to ensure that child windows/views are positioned correctly.
|
||||
- `focusThreeDotMenu()`: Sends a message to the Main process that focuses the view and highlights and focuses the 3-dot menu on Windows/Linux. This is used when the `ALT` key is pressed as a shortcut to focus the menu.
|
||||
|
||||
#### Settings window
|
||||
|
||||

|
||||
|
||||
This window is created when the user opens **Preferences** from the **File** menu. It contains an interface where the user can change settings specific to the Desktop App client that do not affect their Mattermost servers. This window is a child window of the Main Window and will close/hide when the Main Window is closed/hidden.
|
||||
|
||||
This window is managed by the `SettingsWindow` module located at [main/windows/settingsWindow](https://github.com/mattermost/desktop/blob/master/src/main/windows/settingsWindow.ts).
|
||||
|
||||
##### Hooks
|
||||
- `show()`: Shows the Settings Window if it exists and will create it if does not. When the window is closed, the `BrowserWindow` object is dereferenced.
|
||||
- `get()`: Retrieves the Settings Window `BrowserWindow` object if it exists and returns `undefined` if it does not.
|
||||
|
||||
### Views
|
||||
|
||||
These are the internally managed views that are rendered on top of existing windows, adding additional functionality. Each of these views are represented by a `BrowserView` object.
|
||||
|
||||
Most of these views exist as they act as augments to the existing interface and must be rendered over top of the external sandbox Mattermost `BrowserViews`.
|
||||
|
||||
#### Loading screen
|
||||
|
||||

|
||||
|
||||
This is a `BrowserView` that renders over top of external Mattermost views that are loading. It is a cosmetic view that avoids the user having a white screen while the application is loading. The view is ephemeral should only be visible while the current external Mattermost view is loading.
|
||||
|
||||
This view is managed by the `LoadingScreen` module located at [main/views/loadingScreen](https://github.com/mattermost/desktop/blob/master/src/main/views/loadingScreen.ts). Its parent is the Main Window.
|
||||
|
||||
##### Hooks
|
||||
- `show()`: Displays the Loading Screen over top of any other `BrowserView` currently rendered in the Main Window and begins the animation.
|
||||
- `fade()`: Starts the process of removing the Loading Screen. First a signal is sent to the renderer to fade the screen and stop the animation. When that finishes, the view is removed from the window.
|
||||
- `setBounds()`: Calls when the Main Window resizes while the Loading Screen is still visible and the view needs to change its size as well.
|
||||
- `setDarkMode()`: Calls when the application's dark mode flag is changed, to ensure a consistent color scheme.
|
||||
- `isHidden()`: Helper method to check whether the view is hidden or not.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: "Logging"
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
Our application uses the `electron-log` module to do most of our logging. It facilitates both file and console logging.
|
||||
For file logging, you can find the location of the log files by going to **Help** > **View Logs** from within the application.
|
||||
|
||||
Our app supports the following log levels: `error`, `warn`, `info`, `verbose`, `debug`, and `silly`.
|
||||
|
||||
In addition to the library, we provide a **Logger** object that simplifies and streamlines setting up logging for an individual module.
|
||||
To create a **Logger** object, simply create a new one:
|
||||
|
||||
```js
|
||||
import {Logger} from 'common/log';
|
||||
|
||||
const log = new Logger('MyModuleName');
|
||||
```
|
||||
|
||||
You can then use the resulting *log* object to call any of the provided `electron-log` functions, and each log entry with be automatically prefixed with your module name.
|
||||
|
||||
```js
|
||||
// Will print out "[MyModuleName] a long entry"
|
||||
log.debug('a log entry');
|
||||
```
|
||||
|
||||
If you need to add additional prefixing, for example to log events on a specific object instance, we provide the `withPrefix()` method which allows you to add additional prefixes.
|
||||
|
||||
```js
|
||||
// Will print out "[MyModuleName] [some-id] a long entry"
|
||||
const myObjectId = 'some-id';
|
||||
log.withPrefix(myObjectId).debug('a log entry');
|
||||
```
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Navigation"
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
The Desktop App exercises relatively strict control over the user's ability to navigate through the web. This is done for a few reasons:
|
||||
- **Security:** Since we expose certain Electron (and therefore NodeJS) APIs to the front-end application, we want to be in control of what scripts are run in the front-end. We make a concerted effort to lock down the exposed APIs to only what is necessary; however, to avoid any privacy or security breaches, it's best to avoid allowing the user to navigate to any page that isn't explicitly trusted.
|
||||
- **User Experience:** Our application is ONLY designed to work with the Mattermost Web App and thus allowing the user to navigate to other places that are not the Web App is not a supported use case, and could create some undesirable effects.
|
||||
|
||||

|
||||
|
||||
### Internal navigation
|
||||
|
||||
The Mattermost Web App is self-contained, with the majority of links provided by `react-router` and thus most navigation is handled by that module. However, in the Desktop App, we have a major feature that allows users to navigate between distinct tabs bound to the same server. There are two ways that this style of navigation happens in the Web App:
|
||||
- A user clicks on a link provided by the `react-router` `Link` component
|
||||
- The application calls `browserHistory.push` directly within the Web App based on the user action
|
||||
Both of these methods will make use of the `browserHistory` module within the Web App.
|
||||
|
||||
When one of the above methods is used, normally the Web App would update the browser's URL and change the state of the page. In the Desktop App, we instead send the arguments of the call to `browserHistory.push` up to the Electron Main Process. The information is received at the method `WindowManager.handleBrowserHistoryPush`, where we perform the following actions:
|
||||
- **Clean the path name by removing any part of the server's subpath pathname.**
|
||||
- When the arguments are sent up to the Desktop App, it includes the subpath of the server hosting it.
|
||||
- As an example, if the server URL is `http://server-1.com/mattermost`, any path that is received will start with `/mattermost` and we will need to remove that component. The same would be true for any other path following the origin `http://server-1.com`.
|
||||
- **Retrieve the view matching the path name**
|
||||
- After removing the leading subpath (if applicable), we check to see if a portion of the path matches one of the other tabs, signally that we will need to switch to that tab.
|
||||
- For server `http://server-1.com/mattermost`, if the pathname is `/mattermost/boards/board1`, we would get the *Boards* view matching the server.
|
||||
- **Display the correct view and send the cleaned path to its renderer process**
|
||||
- We then explicitly display the new view if it's not currently in focus. If it's closed, we open it and load the corresponding URL with the provided path.
|
||||
- *Exception*: If we're redirecting to the root of the application and the user is not logged in, it will generate an unnecessary refresh. In this case, we do not send the path name down.
|
||||
|
||||
### External navigation
|
||||
|
||||
For the cases where a user wants to navigate away from the Web App to an external site, we generally want to direct the user outside of the Desktop App and have them open their default web browser and use the external site in that application.
|
||||
|
||||
In order to achieve this, we need to explicitly handle every other link and method of navigation that is available to an Electron renderer process. Fortunately, Electron provides a few listeners that help us with that:
|
||||
- [**will-navigate**](https://www.electronjs.org/docs/latest/api/web-contents#event-will-navigate) is an event that fires when the URL is changed for a given renderer process. Attaching a listener for this event allows us to prevent the navigation if desired.
|
||||
- NOTE: The event will not fire for in-page navigations or updating `window.location.hash`.
|
||||
- [**did-start-navigation**](https://www.electronjs.org/docs/latest/api/web-contents#event-did-start-navigation) is another renderer process event that will fire once the page has started navigating. We can use this event to perform any actions when a certain URL is visited.
|
||||
- [**new-window**](https://www.electronjs.org/docs/latest/breaking-changes#removed-webcontents-new-window-event) is an event that will fire when the user tries to open a new window or tab. This commonly will fire when the user clicks on a link marked `target=_blank`. We attach this listener using the `setWindowOpenHandler` and will allow us to `allow` or `deny` the opening as we desire.
|
||||
|
||||
In our application, we define all of these listeners in the `webContentEvents` module, and we attach them whenever a new [webContents](https://www.electronjs.org/docs/latest/api/web-contents) object is create to make sure that all renderer processes are correctly secured and set up correctly.
|
||||
|
||||
#### New window handling
|
||||
Our new window handler will *deny* the opening of a new Electron window if any of the following cases are true:
|
||||
- **Malformed URL:** Depending on the case, it will outright ignore it (if the URL could not be parsed), or it will open the user's default browser if it is somehow invalid in another way.
|
||||
- **Untrusted Protocol:** If the URL does not match an allowed protocol (allowed protocols include `http`, `https`, and any other protocol that was explicitly allowed by the user).
|
||||
- In this case, it will ask the user whether the protocol should be allowed, and if so will open the URL in the user's default application that corresponds to that protocol.
|
||||
- **Unknown Site:** If the URL does not match the root of a configured server, it will always try to open the link in the user's default browser.
|
||||
- If the URL DOES match the root of a configured server, we still will deny the window opening for a few cases:
|
||||
- If the URL matches the public files route (`/api/v4/public/files/*`)
|
||||
- If the URL matches the image proxy route (`/api/v4/image/*`)
|
||||
- If the URL matches the help route (`/help/*`)
|
||||
- For these cases, we will open the link in the user's browser.
|
||||
- **Deep Link Case**: If the URL doesn't match any of the above routes, but is still a valid configured server, we will generally treat is as the deep link cause, and will instead attempt to show the correct tab as well as navigate to the corresponding URL within the app.
|
||||
|
||||
There are two cases where we do allow the application to open a new window:
|
||||
- If the URL matches the `devtools:` protocol, so that we can open the Chrome Developer Tools.
|
||||
- If the URL is a valid configured server URL that corresponds to the plugins route (`/plugins/*`). In these cases we allow a single popup per tab to be opened for certain plugins to do things like OAuth (e.g. GitHub or JIRA).
|
||||
|
||||
Any other case will be automatically denied for security reasons.
|
||||
|
||||
#### Links within the same window
|
||||
By default, the Mattermost Web App marks any link external to its application as `target=_blank`, so that the application doesn't try to open it in the same window. Any other links should therefore be internal to the application.
|
||||
|
||||
We *deny* any sort of in-window navigation with the following exceptions: if the link is a `mailto:` link (which always opens the default mail program), OR if we are in the custom login flow.
|
||||
|
||||
#### Custom login flow
|
||||
In order to facilitate logging into to the app using an external provider (e.g. Okta) in the same way that one would in the browser, we add an exception to the navigation flow that bypasses the `will-navigate` check.
|
||||
|
||||
When a user clicks on a login link that redirects them to a matching URL scheme (listed [here](https://github.com/mattermost/desktop/blob/master/src/common/utils/constants.ts#L48)), we will activate the custom login flow. The URL *MUST* still be internal to the application before we activate this flow, or any URL matching this pattern would allow the app to circumvent the navigation protection.
|
||||
|
||||
While the current window is in the custom login flow, all links that emit the `will-navigate` event will be allowed. Anything that opens a new window will still be restricted based on the rules for new windows. We leave the custom login flow once the app has navigated back to an URL internal to the application
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 118 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Reference in New Issue
Block a user