diff --git a/addons/api/mirage/factories/scope.js b/addons/api/mirage/factories/scope.js
index edd0aeb11..b631c00e0 100644
--- a/addons/api/mirage/factories/scope.js
+++ b/addons/api/mirage/factories/scope.js
@@ -15,6 +15,7 @@ export default factory.extend({
authorized_collection_actions: () => {
return {
+ scopes: ['create', 'list'],
users: ['create', 'list'],
sessions: ['list'],
groups: ['create', 'list'],
diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml
index 49bde4799..9b7a8561d 100644
--- a/addons/core/translations/actions/en-us.yaml
+++ b/addons/core/translations/actions/en-us.yaml
@@ -34,3 +34,5 @@ change-origin: Change Origin URL
change-state: Change State
close: Close
toggle-secret: Toggle secret visibility
+minimize: Minimize
+fullscreen: Fullscreen
diff --git a/ui/admin/app/routes/scopes/scope/auth-methods.js b/ui/admin/app/routes/scopes/scope/auth-methods.js
index 938ce6d16..687c5ef81 100644
--- a/ui/admin/app/routes/scopes/scope/auth-methods.js
+++ b/ui/admin/app/routes/scopes/scope/auth-methods.js
@@ -60,10 +60,14 @@ export default class ScopesScopeAuthMethodsRoute extends Route {
)
async save(authMethod) {
await authMethod.save();
- await this.transitionTo(
- 'scopes.scope.auth-methods.auth-method',
- authMethod
- );
+ if (this.can.can('read model', authMethod)) {
+ await this.transitionTo(
+ 'scopes.scope.auth-methods.auth-method',
+ authMethod
+ );
+ } else {
+ await this.transitionTo('scopes.scope.auth-methods');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method/accounts.js b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method/accounts.js
index d4e1ab55a..6166ae16b 100644
--- a/ui/admin/app/routes/scopes/scope/auth-methods/auth-method/accounts.js
+++ b/ui/admin/app/routes/scopes/scope/auth-methods/auth-method/accounts.js
@@ -60,10 +60,14 @@ export default class ScopesScopeAuthMethodsAuthMethodAccountsRoute extends Route
adapterOptions.password = password;
}
await account.save({ adapterOptions });
- await this.transitionTo(
- 'scopes.scope.auth-methods.auth-method.accounts.account',
- account
- );
+ if (this.can.can('read model', account)) {
+ await this.transitionTo(
+ 'scopes.scope.auth-methods.auth-method.accounts.account',
+ account
+ );
+ } else {
+ await this.transitionTo('scopes.scope.auth-methods.auth-method.accounts');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/credential-libraries.js b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/credential-libraries.js
index 06748f330..d38d9a2f9 100644
--- a/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/credential-libraries.js
+++ b/ui/admin/app/routes/scopes/scope/credential-stores/credential-store/credential-libraries.js
@@ -55,10 +55,16 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
)
async save(credentialLibrary) {
await credentialLibrary.save();
- await this.transitionTo(
- 'scopes.scope.credential-stores.credential-store.credential-libraries.credential-library',
- credentialLibrary
- );
+ if (this.can.can('read model', credentialLibrary)) {
+ await this.transitionTo(
+ 'scopes.scope.credential-stores.credential-store.credential-libraries.credential-library',
+ credentialLibrary
+ );
+ } else {
+ await this.transitionTo(
+ 'scopes.scope.credential-stores.credential-store.credential-libraries'
+ );
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/groups.js b/ui/admin/app/routes/scopes/scope/groups.js
index 1784799cc..e1346ae4d 100644
--- a/ui/admin/app/routes/scopes/scope/groups.js
+++ b/ui/admin/app/routes/scopes/scope/groups.js
@@ -57,7 +57,11 @@ export default class ScopesScopeGroupsRoute extends Route {
)
async save(group) {
await group.save();
- await this.transitionTo('scopes.scope.groups.group', group);
+ if (this.can.can('read model', group)) {
+ await this.transitionTo('scopes.scope.groups.group', group);
+ } else {
+ await this.transitionTo('scopes.scope.groups');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js b/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js
index 36d341bc4..d70b5dab0 100644
--- a/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js
+++ b/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/host-sets.js
@@ -59,10 +59,16 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsRoute extends Rou
)
async save(hostSet) {
await hostSet.save();
- await this.transitionTo(
- 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set',
- hostSet
- );
+ if (this.can.can('read model', hostSet)) {
+ await this.transitionTo(
+ 'scopes.scope.host-catalogs.host-catalog.host-sets.host-set',
+ hostSet
+ );
+ } else {
+ await this.transitionTo(
+ 'scopes.scope.host-catalogs.host-catalog.host-sets'
+ );
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js b/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js
index 5969a8b67..cb91be6ed 100644
--- a/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js
+++ b/ui/admin/app/routes/scopes/scope/host-catalogs/host-catalog/hosts.js
@@ -58,10 +58,14 @@ export default class ScopesScopeHostCatalogsHostCatalogHostsRoute extends Route
)
async save(host) {
await host.save();
- await this.transitionTo(
- 'scopes.scope.host-catalogs.host-catalog.hosts.host',
- host
- );
+ if (this.can.can('read model', host)) {
+ await this.transitionTo(
+ 'scopes.scope.host-catalogs.host-catalog.hosts.host',
+ host
+ );
+ } else {
+ await this.transitionTo('scopes.scope.host-catalogs.host-catalog.hosts');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/roles.js b/ui/admin/app/routes/scopes/scope/roles.js
index cbc1dfcc5..f83c69135 100644
--- a/ui/admin/app/routes/scopes/scope/roles.js
+++ b/ui/admin/app/routes/scopes/scope/roles.js
@@ -58,7 +58,11 @@ export default class ScopesScopeRolesRoute extends Route {
)
async save(role) {
await role.save();
- await this.transitionTo('scopes.scope.roles.role', role);
+ if (this.can.can('read model', role)) {
+ await this.transitionTo('scopes.scope.roles.role', role);
+ } else {
+ await this.transitionTo('scopes.scope.roles');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/targets.js b/ui/admin/app/routes/scopes/scope/targets.js
index 2adb5ca84..85a27eab1 100644
--- a/ui/admin/app/routes/scopes/scope/targets.js
+++ b/ui/admin/app/routes/scopes/scope/targets.js
@@ -60,7 +60,11 @@ export default class ScopesScopeTargetsRoute extends Route {
)
async save(target) {
await target.save();
- await this.transitionTo('scopes.scope.targets.target', target);
+ if (this.can.can('read model', target)) {
+ await this.transitionTo('scopes.scope.targets.target', target);
+ } else {
+ await this.transitionTo('scopes.scope.targets');
+ }
this.refresh();
}
diff --git a/ui/admin/app/routes/scopes/scope/users.js b/ui/admin/app/routes/scopes/scope/users.js
index aa3dde96a..6512c6aeb 100644
--- a/ui/admin/app/routes/scopes/scope/users.js
+++ b/ui/admin/app/routes/scopes/scope/users.js
@@ -59,7 +59,11 @@ export default class ScopesScopeUsersRoute extends Route {
)
async save(user) {
await user.save();
- await this.transitionTo('scopes.scope.users.user', user);
+ if (this.can.can('read model', user)) {
+ await this.transitionTo('scopes.scope.users.user', user);
+ } else {
+ await this.transitionTo('scopes.scope.users');
+ }
this.refresh();
}
diff --git a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
index 9297cfd32..500beb452 100644
--- a/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/auth-methods/index.hbs
@@ -12,28 +12,25 @@
-
{{#if (can 'create collection' this.scopeModel collection='auth-methods')}}
- {{#if @model}}
-
+
-
- {{t 'resources.auth-method.types.password'}}
-
-
- {{t 'resources.auth-method.types.oidc'}}
-
-
- {{/if}}
+ {{t 'resources.auth-method.types.password'}}
+
+
+ {{t 'resources.auth-method.types.oidc'}}
+
+
{{/if}}
@@ -168,11 +165,13 @@
as |message|
>
- {{#if (can 'list collection' this.scope collection='auth-methods')}}
+ {{#if
+ (can 'list collection' this.scopeModel collection='auth-methods')
+ }}
{{! can list (at least): show default welcome message}}
{{t 'resources.auth-method.messages.welcome.description'}}
{{else if (can
- 'create collection' this.scope collection='auth-methods'
+ 'create collection' this.scopeModel collection='auth-methods'
)}}
{{! can create (only): show create-but-not-list welcome message}}
{{t
@@ -187,19 +186,6 @@
}}
{{/if}}
-
-
- {{t 'titles.new'}}
-
- {{#if (can 'create collection' this.scope collection='auth-methods')}}
-
-
- {{t 'titles.new'}}
-
- {{/if}}
diff --git a/ui/admin/app/templates/scopes/scope/groups/index.hbs b/ui/admin/app/templates/scopes/scope/groups/index.hbs
index 1e5f038db..2026ac1c5 100644
--- a/ui/admin/app/templates/scopes/scope/groups/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/groups/index.hbs
@@ -71,7 +71,6 @@
as |message|
>
- {{t 'resources.group.description'}}
{{#if (can 'list collection' this.scope collection='groups')}}
{{! can list (at least): show default welcome message}}
{{t 'resources.group.description'}}
diff --git a/ui/admin/app/templates/scopes/scope/scopes/index.hbs b/ui/admin/app/templates/scopes/scope/scopes/index.hbs
index 19a4168d5..4194cdc24 100644
--- a/ui/admin/app/templates/scopes/scope/scopes/index.hbs
+++ b/ui/admin/app/templates/scopes/scope/scopes/index.hbs
@@ -26,10 +26,12 @@
- {{#if @model.subScopes}}
-
- {{t 'titles.new'}}
-
+ {{#if (can 'create collection' @model.currentScope collection='scopes')}}
+ {{#if @model.subScopes}}
+
+ {{t 'titles.new'}}
+
+ {{/if}}
{{/if}}
@@ -65,10 +67,14 @@
{{t 'resources.org.description'}}
-
-
- {{t 'titles.new'}}
-
+ {{#if
+ (can 'create collection' @model.currentScope collection='scopes')
+ }}
+
+
+ {{t 'titles.new'}}
+
+ {{/if}}
{{/if}}
@@ -82,10 +88,14 @@
{{t 'resources.project.description'}}
-
-
- {{t 'titles.new'}}
-
+ {{#if
+ (can 'create collection' @model.currentScope collection='scopes')
+ }}
+
+
+ {{t 'titles.new'}}
+
+ {{/if}}
{{/if}}
diff --git a/ui/desktop/.gitignore b/ui/desktop/.gitignore
index 7e0f7ddce..f414c569a 100644
--- a/ui/desktop/.gitignore
+++ b/ui/desktop/.gitignore
@@ -24,3 +24,6 @@
/.node_modules.ember-try/
/bower.json.ember-try
/package.json.ember-try
+
+# Vagrant
+.vagrant/
diff --git a/ui/desktop/CHANGELOG.md b/ui/desktop/CHANGELOG.md
index eeb56bd30..c02fcc34f 100644
--- a/ui/desktop/CHANGELOG.md
+++ b/ui/desktop/CHANGELOG.md
@@ -4,6 +4,12 @@ Canonical reference for changes, improvements, and bugfixes for Boundary Desktop
## Next
+## v1.3.0 [CLI 0.6.0] (2021.09.09)
+
+### New
+
+- Add Debian based linux support for client. ([PR](https://github.com/hashicorp/boundary-ui/pull/719))
+
## v1.2.1 [CLI 0.5.0] (2021.08.03)
### New
diff --git a/ui/desktop/README.md b/ui/desktop/README.md
index 82ef7d587..8efc3e47f 100644
--- a/ui/desktop/README.md
+++ b/ui/desktop/README.md
@@ -41,6 +41,7 @@ List of available project commands. `yarn run `
| ------- | ----------- |
| build:development | Builds the UI in development mode. |
| build | Builds the UI for production. |
+| build:desktop:debianOnMacOS | Builds debian based linux artifacts on MacOS. |
| lint | Runs all lint commands. |
| lint:hbs | Lints `hbs` template files. |
| lint:js | Lints `js` files. |
@@ -76,6 +77,7 @@ These environment variables may be used to customized the build.
| `APP_UPDATER_CURRENT_VERSION` | Version of client. |
| `APP_UPDATER_LATEST_VERSION_TAG` | Next version for comparison with current version. |
| `APP_UPDATER_LATEST_VERSION_LOCATION` | Location of app release to use for updating client. Can be a filepath or url. |
+| `BYPASS_CLI_SETUP` | Disable download and extraction of cli. For development use only. |
### Building for Production
@@ -89,12 +91,20 @@ yarn build
```
`BOUNDARY_DESKTOP_SIGNING_IDENTITY` environment variable must be provided
-to codesign in production.
+to codesign MacOS artifacts in production.
The static production assets are saved into the `dist/` folder.
The Boundary CLI is downloaded and extracted to `electron-app/cli/` folder as part of
packaging. CLI version is defined in `electron-app/config/cli.js`.
+To build debian based linux artifacts on MacOS, additional [MacOS tools](https://www.electronforge.io/config/makers/deb) need to be installed before running the following commands from this folder.
+
+```
+yarn install
+yarn build:production # Build assets
+yarn build:desktop:debianOnMacOS # Build app
+```
+
#### Environment Variables
These environment variables may be used to customized the build.
diff --git a/ui/desktop/app/controllers/application.js b/ui/desktop/app/controllers/application.js
index 0eb5226e0..10cf5fcc7 100644
--- a/ui/desktop/app/controllers/application.js
+++ b/ui/desktop/app/controllers/application.js
@@ -1,6 +1,7 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import config from '../config/environment';
+import { computed } from '@ember/object';
export default class ApplicationController extends Controller {
// =services
@@ -10,4 +11,17 @@ export default class ApplicationController extends Controller {
// =attributes
notifyTimeout = config.notifyTimeout;
+
+ // =attributes
+
+ /**
+ * Display OS window actions (minimize, fullscreen, close) for
+ * Windows and Linux as OS frame/shell is disable.
+ * Does not apply to MacOS.
+ * @type {boolean}
+ */
+ @computed('isMacOS')
+ get isFrameless() {
+ return !this.isMacOS;
+ }
}
diff --git a/ui/desktop/app/routes/application.js b/ui/desktop/app/routes/application.js
index f2f8e11fe..4acb8a175 100644
--- a/ui/desktop/app/routes/application.js
+++ b/ui/desktop/app/routes/application.js
@@ -31,11 +31,10 @@ export default class ApplicationRoute extends Route {
}
/**
- * Add OS config on controller
+ * Add OS config on controller.
*/
async setupController(controller) {
controller.set('isMacOS', await this.ipc.invoke('isMacOS'));
- controller.set('isWindowsOS', await this.ipc.invoke('isWindowsOS'));
}
// =actions
diff --git a/ui/desktop/app/templates/application.hbs b/ui/desktop/app/templates/application.hbs
index 0099725ed..501eb1db1 100644
--- a/ui/desktop/app/templates/application.hbs
+++ b/ui/desktop/app/templates/application.hbs
@@ -1,7 +1,7 @@
{{page-title (app-name)}}
@@ -19,23 +19,26 @@
{{/if}}
- {{#if this.isWindowsOS}}
+ {{#if this.isFrameless}}
{{/if}}
diff --git a/ui/desktop/electron-app/assets/app-icons/icon.png b/ui/desktop/electron-app/assets/app-icons/icon.png
new file mode 100644
index 000000000..9d162ec10
Binary files /dev/null and b/ui/desktop/electron-app/assets/app-icons/icon.png differ
diff --git a/ui/desktop/electron-app/config/cli.js b/ui/desktop/electron-app/config/cli.js
index c2f06d13d..2cb9a4174 100644
--- a/ui/desktop/electron-app/config/cli.js
+++ b/ui/desktop/electron-app/config/cli.js
@@ -3,13 +3,12 @@ const os = require('os');
const path = require('path');
const https = require('https');
const decompress = require('decompress');
-const { isMac, isWindows } = require('../src/helpers/platform.js');
+const { isMac, isWindows, isLinux } = require('../src/helpers/platform.js');
const artifactDestination = path.resolve(__dirname, '..', 'cli');
const downloadArtifact = (version) => {
const archivePlatform = {};
- // TODO: Support all available build machines
if (isMac()) {
archivePlatform.name = 'darwin';
archivePlatform.arch = 'amd64';
@@ -20,6 +19,24 @@ const downloadArtifact = (version) => {
archivePlatform.arch = 'amd64';
}
+ if (isLinux()) {
+ let arch = os.arch();
+ // Map x64 to amd64 cli artifact
+ if (arch.match(/(x64)/i)) arch = 'amd64';
+ archivePlatform.name = os.platform();
+ archivePlatform.arch = arch;
+ }
+
+ // Set cli artifact to linux-amd64 when building debian artifacts on macOS
+ if (process.env.BUILD_DEBIAN) {
+ archivePlatform.name = 'linux';
+ archivePlatform.arch = 'amd64';
+ }
+
+ console.log(
+ `Download cli for platform: ${archivePlatform.name} arch: ${archivePlatform.arch}`
+ );
+
const archiveName = `boundary_${version}_${archivePlatform.name}_${archivePlatform.arch}.zip`;
const url = `https://releases.hashicorp.com/boundary/${version}/${archiveName}`;
return new Promise((resolve, reject) => {
diff --git a/ui/desktop/electron-app/config/cli/VERSION b/ui/desktop/electron-app/config/cli/VERSION
index 79a2734bb..09a3acfa1 100644
--- a/ui/desktop/electron-app/config/cli/VERSION
+++ b/ui/desktop/electron-app/config/cli/VERSION
@@ -1 +1 @@
-0.5.0
\ No newline at end of file
+0.6.0
\ No newline at end of file
diff --git a/ui/desktop/electron-app/config/desktop.js b/ui/desktop/electron-app/config/desktop.js
index af9c8f5de..87588619f 100644
--- a/ui/desktop/electron-app/config/desktop.js
+++ b/ui/desktop/electron-app/config/desktop.js
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
+const { isLinux } = require('../src/helpers/platform.js');
// Create config
const createConfig = () => {
@@ -9,8 +10,16 @@ const createConfig = () => {
copyright: `Copyright © ${new Date().getFullYear()} HashiCorp, Inc.`,
releaseVersion: process.env.RELEASE_VERSION,
releaseCommit: process.env.RELEASE_COMMIT,
+ executableName: 'Boundary',
};
+ if (process.env.BUILD_DEBIAN) {
+ config.name = 'boundary-desktop';
+ config.productName = 'boundary-desktop';
+ }
+
+ if (isLinux() || process.env.BUILD_DEBIAN) config.executableName = 'boundary-desktop';
+
if (!config.releaseVersion) config.releaseVersion = '0.0.0';
return config;
};
diff --git a/ui/desktop/electron-app/config/forge.config.js b/ui/desktop/electron-app/config/forge.config.js
index 63755fde4..8b12936fc 100644
--- a/ui/desktop/electron-app/config/forge.config.js
+++ b/ui/desktop/electron-app/config/forge.config.js
@@ -1,12 +1,19 @@
// Generated during build
const config = require('./config.js');
const { isMac } = require('../src/helpers/platform.js');
+const fs = require('fs');
+const path = require('path');
console.log(`\n[forge-config] Release commit: ${config.releaseCommit}`);
console.log(`[forge-config] Release version: ${config.releaseVersion}`);
-// MacOS signing identity
-if (isMac() && !process.env.BOUNDARY_DESKTOP_SIGNING_IDENTITY)
+// MacOS signing identity.
+// Ignore signing identity warning for debian builds run on MacOS
+if (
+ isMac() &&
+ !process.env.BOUNDARY_DESKTOP_SIGNING_IDENTITY &&
+ !process.env.BUILD_DEBIAN
+)
console.warn(
'[forge-config] WARNING: Could not find signing identity. Proceeding without signing.'
);
@@ -16,9 +23,10 @@ module.exports = {
ignore: ['/ember-test(/|$)', '/tests(/|$)'],
icon: './assets/app-icons/icon',
name: config.productName,
- appVersion: config.version,
+ appVersion: config.releaseVersion,
appBundleId: 'com.electron.boundary',
appCopyright: config.copyright,
+ executableName: config.executableName,
osxSign: {
identity: process.env.BOUNDARY_DESKTOP_SIGNING_IDENTITY,
'hardened-runtime': true,
@@ -43,5 +51,48 @@ module.exports = {
{
name: '@electron-forge/maker-squirrel',
},
+ {
+ name: '@electron-forge/maker-deb',
+ config: {
+ options: {
+ name: 'boundary-desktop',
+ version: config.releaseVersion,
+ icon: './assets/app-icons/icon.png',
+ description: 'Desktop Client for Boundary',
+ productDescription: 'Desktop Client for Boundary',
+ },
+ },
+ },
],
+ hooks: {
+ postPackage: async (forgeConfig, options) => {
+ if (options.spinner) {
+ options.spinner.info(
+ `Packaged for ${options.platform}-${options.arch} at ${options.outputPaths[0]}`
+ );
+ }
+ },
+ postMake: (forgeConfig, options) => {
+ // Copy artifacts into release folder
+ options.forEach(({ artifacts, platform, arch }) => {
+ // Generate release name
+ const version = forgeConfig.packagerConfig.appVersion;
+ const destination = path.join('out', 'release', version);
+ if (!fs.existsSync(destination))
+ fs.mkdirSync(destination, { recursive: true });
+ // Copy artifacts
+ artifacts.forEach(async (artifact) => {
+ const name = `boundary-desktop_${version}_${platform}_${arch}${path.extname(artifact)}`;
+ const artifactDestination = path.join(destination, name);
+ console.log(`[release] Found artifact: ${artifact}`);
+ try {
+ await fs.promises.copyFile(artifact, artifactDestination);
+ console.log(`[release] Copied artifact: ${path.resolve(artifactDestination)}`);
+ } catch (e) {
+ console.warn(`[release] Could not copy ${artifact}`, e);
+ }
+ });
+ });
+ },
+ },
};
diff --git a/ui/desktop/electron-app/package.json b/ui/desktop/electron-app/package.json
index a91471f79..84a869fb4 100644
--- a/ui/desktop/electron-app/package.json
+++ b/ui/desktop/electron-app/package.json
@@ -1,5 +1,5 @@
{
- "name": "desktop",
+ "name": "boundary-desktop",
"productName": "Boundary",
"version": "0.0.0",
"private": true,
@@ -33,6 +33,7 @@
},
"devDependencies": {
"@electron-forge/cli": "6.0.0-beta.54",
+ "@electron-forge/maker-deb": "6.0.0-beta.54",
"@electron-forge/maker-dmg": "^6.0.0-beta.54",
"@electron-forge/maker-squirrel": "^6.0.0-beta.55",
"@electron-forge/maker-zip": "^6.0.0-beta.54",
diff --git a/ui/desktop/electron-app/src/helpers/app-updater.js b/ui/desktop/electron-app/src/helpers/app-updater.js
index d36d18fff..70e4a8426 100644
--- a/ui/desktop/electron-app/src/helpers/app-updater.js
+++ b/ui/desktop/electron-app/src/helpers/app-updater.js
@@ -4,7 +4,7 @@ const https = require('https');
const semver = require('semver');
const { parse } = require('node-html-parser');
const { autoUpdater, dialog } = require('electron');
-const { isWindows } = require('../helpers/platform.js');
+const { isWindows, isLinux } = require('../helpers/platform.js');
const config = require('../../config/config.js');
let currentVersion = config.releaseVersion;
@@ -124,8 +124,11 @@ const displayDownloadPrompt = (version, url) => {
**/
module.exports = {
run: async ({ suppressNoUpdatePrompt } = {}) => {
- // Do nothing on Windows - yet
- if (isWindows()) return;
+ /**
+ * Disable app updater check for linux as update is unsupported.
+ * TODO: Enable for windows pending feature dev. Windows is supported.
+ */
+ if (isWindows() || isLinux()) return;
let latestVersion;
if (debug) {
diff --git a/ui/desktop/electron-app/src/helpers/platform.js b/ui/desktop/electron-app/src/helpers/platform.js
index 5e508ef6c..1fd98fcc4 100644
--- a/ui/desktop/electron-app/src/helpers/platform.js
+++ b/ui/desktop/electron-app/src/helpers/platform.js
@@ -3,4 +3,5 @@ const os = require('os');
module.exports = {
isMac: () => Boolean(os.platform().match(/(darwin)/i)),
isWindows: () => Boolean(os.platform().match(/(win32)/i)),
+ isLinux: () => Boolean(os.platform().match(/(linux)/i)),
};
diff --git a/ui/desktop/electron-app/src/index.js b/ui/desktop/electron-app/src/index.js
index c0c437698..66272336a 100644
--- a/ui/desktop/electron-app/src/index.js
+++ b/ui/desktop/electron-app/src/index.js
@@ -22,7 +22,7 @@ const sessionManager = require('./services/session-manager.js');
const menu = require('./config/menu.js');
const appUpdater = require('./helpers/app-updater.js');
-const { isWindows } = require('./helpers/platform.js');
+const { isMac, isLinux } = require('./helpers/platform.js');
const isDev = require('electron-is-dev');
// Register the custom file protocol
@@ -113,11 +113,11 @@ app.on('ready', async () => {
}
Menu.setApplicationMenu(menuTemplate);
- mainWindow = new BrowserWindow({
+ const browserWindowOptions = {
width: 1280,
height: 760,
titleBarStyle: 'hiddenInset',
- frame: !isWindows(),
+ frame: isMac(),
webPreferences: {
partition,
sandbox: true,
@@ -131,7 +131,14 @@ app.on('ready', async () => {
preload: preloadPath /* eng-disable PRELOAD_JS_CHECK */,
disableBlinkFeatures: 'Auxclick',
},
- });
+ };
+
+ // To show app icon in toolbar in linux, set browser window icon.
+ // This is a limitation of electron build.
+ if (isLinux())
+ browserWindowOptions.icon = path.join(__dirname, '..', 'assets', 'app-icons', 'icon.png');
+
+ mainWindow = new BrowserWindow(browserWindowOptions);
// If the user-specified origin changes, reload the page so that
// the CSP can be refreshed with the this source allowed
diff --git a/ui/desktop/electron-app/src/ipc/handlers.js b/ui/desktop/electron-app/src/ipc/handlers.js
index d5aac6fb4..d66182f4c 100644
--- a/ui/desktop/electron-app/src/ipc/handlers.js
+++ b/ui/desktop/electron-app/src/ipc/handlers.js
@@ -5,7 +5,7 @@ const boundaryCli = require('../cli/index.js');
const sessionManager = require('../services/session-manager.js');
const runtimeSettings = require('../services/runtime-settings.js');
const sanitizer = require('../utils/sanitizer.js');
-const { isMac, isWindows } = require('../helpers/platform.js');
+const { isMac } = require('../helpers/platform.js');
/**
* Returns the current runtime origin, which is used by the main thread to
@@ -38,8 +38,10 @@ handle('openExternal', async (href) => {
const isLocalhost =
href.startsWith('http://localhost') || href.startsWith('http://127.0.0.1');
if (isSecure || isLocalhost || isDev) {
- // openExternal is necessary in order to display documentation and to
- // support arbitrary OIDC flows. The protocol is validated (see above).
+ /**
+ * Launch browser to display documentation and to support arbitrary OIDC flows
+ * using openExternal. The protocol is validated (see above).
+ */
shell.openExternal(href); /* eng-disable OPEN_EXTERNAL_JS_CHECK */
} else {
throw new Error(
@@ -71,11 +73,6 @@ handle('stop', ({ session_id }) => sessionManager.stopById(session_id));
*/
handle('isMacOS', () => isMac());
-/**
- * Check for Windows OS
- */
-handle('isWindowsOS', () => isWindows());
-
/**
* Minimize window
*/
diff --git a/ui/desktop/electron-app/yarn.lock b/ui/desktop/electron-app/yarn.lock
index c4bd48ac9..494209a03 100644
--- a/ui/desktop/electron-app/yarn.lock
+++ b/ui/desktop/electron-app/yarn.lock
@@ -164,6 +164,16 @@
fs-extra "^9.0.1"
which "^2.0.2"
+"@electron-forge/maker-deb@6.0.0-beta.54":
+ version "6.0.0-beta.54"
+ resolved "https://registry.yarnpkg.com/@electron-forge/maker-deb/-/maker-deb-6.0.0-beta.54.tgz#00aa6d7fd7c6b5984079c374b24a3c99052ed379"
+ integrity sha512-PEAYULi7n/JkwvaEQnM554ewmLYkxGtHvuh6vUf5wsh48Xw3jcEVHejsc4FDjx5I6cKAByb9nscTtZpKt3ngXw==
+ dependencies:
+ "@electron-forge/maker-base" "6.0.0-beta.54"
+ "@electron-forge/shared-types" "6.0.0-beta.54"
+ optionalDependencies:
+ electron-installer-debian "^3.0.0"
+
"@electron-forge/maker-dmg@^6.0.0-beta.54":
version "6.0.0-beta.54"
resolved "https://registry.yarnpkg.com/@electron-forge/maker-dmg/-/maker-dmg-6.0.0-beta.54.tgz#c3777b28c30c03b3dc18d1ca332d27f8c78c65b1"
@@ -287,7 +297,7 @@
global-agent "^2.0.2"
global-tunnel-ng "^2.7.1"
-"@malept/cross-spawn-promise@^1.1.0", "@malept/cross-spawn-promise@^1.1.1":
+"@malept/cross-spawn-promise@^1.0.0", "@malept/cross-spawn-promise@^1.1.0", "@malept/cross-spawn-promise@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d"
integrity sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==
@@ -328,6 +338,13 @@
"@types/node" "*"
"@types/responselike" "*"
+"@types/fs-extra@^9.0.1":
+ version "9.0.12"
+ resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-9.0.12.tgz#9b8f27973df8a7a3920e8461517ebf8a7d4fdfaf"
+ integrity sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==
+ dependencies:
+ "@types/node" "*"
+
"@types/glob@^7.1.1":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
@@ -721,6 +738,15 @@ cli-width@^3.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+cliui@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
+ integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^6.2.0"
+
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@@ -917,7 +943,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
dependencies:
ms "2.1.2"
-decamelize@^1.1.2:
+decamelize@^1.1.2, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -1115,6 +1141,37 @@ electron-devtools-installer@^3.1.1:
semver "^7.2.1"
unzip-crx-3 "^0.2.0"
+electron-installer-common@^0.10.2:
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/electron-installer-common/-/electron-installer-common-0.10.3.tgz#40f9db644ca60eb28673d545b67ee0113aef4444"
+ integrity sha512-mYbP+6i+nHMIm0WZHXgGdmmXMe+KXncl6jZYQNcCF9C1WsNA9C5SZ2VP4TLQMSIoFO+X4ugkMEA5uld1bmyEvA==
+ dependencies:
+ "@malept/cross-spawn-promise" "^1.0.0"
+ asar "^3.0.0"
+ debug "^4.1.1"
+ fs-extra "^9.0.0"
+ glob "^7.1.4"
+ lodash "^4.17.15"
+ parse-author "^2.0.0"
+ semver "^7.1.1"
+ tmp-promise "^3.0.2"
+ optionalDependencies:
+ "@types/fs-extra" "^9.0.1"
+
+electron-installer-debian@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/electron-installer-debian/-/electron-installer-debian-3.1.0.tgz#2f6107f559f6564c44e3832fb2942dd8de4d40cc"
+ integrity sha512-k6KChvx0Fw8XTlCqwwbBfh19yGQaKjGdbugokmr1IpzINOm4QFyACKMTHAYFHW5LCBUZQShZD96hwxUZ+8Kx+w==
+ dependencies:
+ "@malept/cross-spawn-promise" "^1.0.0"
+ debug "^4.1.1"
+ electron-installer-common "^0.10.2"
+ fs-extra "^9.0.0"
+ get-folder-size "^2.0.1"
+ lodash "^4.17.4"
+ word-wrap "^1.2.3"
+ yargs "^15.0.1"
+
electron-installer-dmg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/electron-installer-dmg/-/electron-installer-dmg-3.0.0.tgz#08935b602f3120981c8d5fd24d3f6525f8b0198a"
@@ -1411,7 +1468,7 @@ find-up@^2.0.0:
dependencies:
locate-path "^2.0.0"
-find-up@^4.0.0:
+find-up@^4.0.0, find-up@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
@@ -1536,6 +1593,11 @@ galactus@^0.2.1:
flora-colossus "^1.0.0"
fs-extra "^4.0.0"
+gar@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/gar/-/gar-1.0.4.tgz#f777bc7db425c0572fdeb52676172ca1ae9888b8"
+ integrity sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==
+
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -1564,11 +1626,19 @@ generate-object-property@^1.1.0:
dependencies:
is-property "^1.0.0"
-get-caller-file@^2.0.5:
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+get-folder-size@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/get-folder-size/-/get-folder-size-2.0.1.tgz#3fe0524dd3bad05257ef1311331417bcd020a497"
+ integrity sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==
+ dependencies:
+ gar "^1.0.4"
+ tiny-each-async "2.0.3"
+
get-installed-path@^2.0.3:
version "2.1.1"
resolved "https://registry.yarnpkg.com/get-installed-path/-/get-installed-path-2.1.1.tgz#a1f33dc6b8af542c9331084e8edbe37fe2634152"
@@ -2172,7 +2242,7 @@ lodash.templatesettings@^4.0.0:
dependencies:
lodash._reinterpolate "^3.0.0"
-lodash@^4.17.10, lodash@^4.17.19, lodash@^4.17.20:
+lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -3055,6 +3125,11 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
resolve-alpn@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.1.1.tgz#4a006a7d533c81a5dd04681612090fde227cd6e1"
@@ -3192,7 +3267,7 @@ semver@^6.2.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
-semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5:
+semver@^7.1.1, semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
@@ -3206,7 +3281,7 @@ serialize-error@^7.0.1:
dependencies:
type-fest "^0.13.1"
-set-blocking@~2.0.0:
+set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -3505,6 +3580,11 @@ through@^2.3.6, through@^2.3.8:
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+tiny-each-async@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-each-async/-/tiny-each-async-2.0.3.tgz#8ebbbfd6d6295f1370003fbb37162afe5a0a51d1"
+ integrity sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=
+
tmp-promise@^1.0.5:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-1.1.0.tgz#bb924d239029157b9bc1d506a6aa341f8b13e64c"
@@ -3513,6 +3593,13 @@ tmp-promise@^1.0.5:
bluebird "^3.5.0"
tmp "0.1.0"
+tmp-promise@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.2.tgz#6e933782abff8b00c3119d63589ca1fb9caaa62a"
+ integrity sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==
+ dependencies:
+ tmp "^0.2.0"
+
tmp@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877"
@@ -3527,6 +3614,13 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
+tmp@^0.2.0:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+ integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+ dependencies:
+ rimraf "^3.0.0"
+
tn1150@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/tn1150/-/tn1150-0.1.0.tgz#673503d24d56b87de8b8c77fee3fc0853d59a18d"
@@ -3699,6 +3793,11 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"
+which-module@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
+
which@^1.2.14, which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -3720,6 +3819,20 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2 || 2"
+word-wrap@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -3756,6 +3869,11 @@ xtend@~2.1.1:
dependencies:
object-keys "~0.4.0"
+y18n@^4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
+ integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
+
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
@@ -3771,11 +3889,28 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-yargs-parser@^20.0.0, yargs-parser@^20.2.2, yargs-parser@~20.2.7:
+yargs-parser@^18.1.2, yargs-parser@^20.0.0, yargs-parser@^20.2.2, yargs-parser@~20.2.7:
version "20.2.7"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
+yargs@^15.0.1:
+ version "15.4.1"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+ integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+ dependencies:
+ cliui "^6.0.0"
+ decamelize "^1.2.0"
+ find-up "^4.1.0"
+ get-caller-file "^2.0.1"
+ require-directory "^2.1.1"
+ require-main-filename "^2.0.0"
+ set-blocking "^2.0.0"
+ string-width "^4.2.0"
+ which-module "^2.0.0"
+ y18n "^4.0.0"
+ yargs-parser "^18.1.2"
+
yargs@^16.0.0:
version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
diff --git a/ui/desktop/environments/ubuntu-focal64/Vagrantfile b/ui/desktop/environments/ubuntu-focal64/Vagrantfile
new file mode 100644
index 000000000..0d647d6da
--- /dev/null
+++ b/ui/desktop/environments/ubuntu-focal64/Vagrantfile
@@ -0,0 +1,107 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+=begin
+This vagrant script is used to setup Ubuntu in Virtualbox and deploy both the desktop client and cli
+in preparation for testing linux support for desktop client.
+
+Install vagrant guest additions plugin: `vagrant plugin install vagrant-vbguest`.
+
+## Setup Desktop
+For using locally built debian artifacts:
+- Refer to 'Building for Production' section in /boundary-ui/ui/desktop/README to build debian
+ artifacts on MacOS
+
+## Setup Ubuntu
+- Create a ubuntu desktop box using vagrant: `vagrant up --provision-with setup,cli,staged-desktop`.
+- Desktop client artifact and cli will be available in `/home/vagrant/Desktop` after logging into ubuntu.
+ Username/password for login: vagrant/vagrant. Navigate to `/home/vagrant/Desktop` in a terminal app.
+- To install desktop app use either `apt` or `dpkg`
+ - `sudo apt install ./boundary-desktop_1.3.0_linux_amd64.deb`
+ - `sudo dpkg -i ./boundary-desktop_1.3.0_linux_amd64.deb`
+ - To launch desktop client from terminal: `boundary-desktop`
+- To launch cli: `./boundary dev`
+
+## Provision types
+User --provision-with option to setup machine for either cli or development
+Setup for testing staged desktop release:
+ vagrant up --provision-with setup,cli,staged-desktop
+Setup for testing artifacts built locally:
+ vagrant up --provision-with setup,cli
+Setup for developing desktop client:
+ vagrant up --provision-with setup,development
+To destroy machine:
+ vagrant destroy -f
+=end
+
+Vagrant.configure("2") do |config|
+ config.vm.box = "ubuntu/focal64"
+
+ # Share desktop artifacts folder
+ config.vm.synced_folder "../../../out/release", "/vagrant-desktop-app", create: true, owner: "vagrant", group: "vagrant", automount: true
+
+ config.vm.provider "virtualbox" do |vb|
+ # Display the VirtualBox GUI when booting the machine
+ vb.gui = true
+ # Customize the amount of memory on the VM:
+ vb.memory = "4096"
+ end
+
+ config.vm.provision "setup", type: "shell", inline: <<-SHELL
+ sudo apt-get update -y
+ sudo apt-get upgrade -y
+ sudo apt-get install curl firefox
+ # Add vagrant to administrator group
+ sudo usermod -aG sudo vagrant
+ # Add vagrant to shared folder
+ sudo usermod -aG vboxsf vagrant
+ SHELL
+
+ # Setup for testing desktop
+ config.vm.provision "cli", type: "shell", inline: <<-SHELL
+ # Install ubuntu desktop GUI
+ # For GNOME desktop:
+ # sudo apt install gnome-session gnome-terminal
+ sudo apt-get install -y --no-install-recommends lubuntu-desktop
+ # Setup boundary cli
+ sudo apt-get install docker.io -y
+ sudo groupadd docker
+ sudo usermod -aG docker vagrant
+ sudo apt-get install -y unzip
+ curl https://releases.hashicorp.com/boundary/0.5.0/boundary_0.5.0_linux_amd64.zip -o boundary-cli.zip
+ unzip -o boundary-cli.zip -d /home/vagrant/Desktop/
+ # Setup localhost ssh
+ yes | ssh-keygen -t rsa -N "" -f /home/vagrant/.ssh/id_rsa -C vagrant@ubuntu-focal
+ cat /home/vagrant/.ssh/id_rsa.pub >> /home/vagrant/.ssh/authorized_keys
+ sudo chown -R vagrant:vagrant .ssh
+ # Restart
+ # sudo shutdown -r now
+ SHELL
+
+ # Setup for developing desktop
+ config.vm.provision "development", type: "shell", inline: <<-SHELL
+ # Setup node 12 source
+ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
+ sudo apt-get install -y nodejs
+
+ sudo apt-get remove cmdtest
+ sudo apt-get install -y npm git chromium-browser
+
+ git clone https://github.com/hashicorp/boundary-ui.git /home/vagrant/Desktop/boundary-ui
+ sudo npm install -g yarn
+
+ # Install boundary-ui dependencies
+ cd /home/vagrant/Desktop/boundary-ui
+ yarn install
+ SHELL
+
+ config.vm.provision "staged-desktop", type: "shell", inline: <<-SHELL
+ # Download staged desktop
+ sudo apt install wget -y
+ wget -P /home/vagrant/Desktop/ http://hc-releases-boundary-desktop-staging.s3-website-us-east-1.amazonaws.com/boundary-desktop/1.3.0/boundary-desktop_1.3.0_linux_amd64.deb
+ # Install
+ sudo apt install /home/vagrant/Desktop/boundary-desktop_1.3.0_linux_amd64.deb
+ SHELL
+
+ config.vm.post_up_message = "Login using username/password: vagrant/vagrant.\nArtifacts: /home/vagrant/Desktop"
+end
diff --git a/ui/desktop/package.json b/ui/desktop/package.json
index 77482183b..7cc33278c 100755
--- a/ui/desktop/package.json
+++ b/ui/desktop/package.json
@@ -15,7 +15,9 @@
"build:production": "cross-env EMBER_CLI_ELECTRON=true ember build --environment=production",
"build:development": "ember build",
"prebuild:desktop": "cross-os prebuild:desktop",
- "build:desktop": "cd electron-app && yarn install && yarn make",
+ "build:desktop": "yarn build:desktop:install && yarn --cwd electron-app make",
+ "build:desktop:debianOnMacOS": "yarn build:desktop:install && BUILD_DEBIAN=true yarn --cwd electron-app make --platform linux --arch x64",
+ "build:desktop:install": "yarn install --cwd electron-app",
"lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
"lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
"lint:hbs": "ember-template-lint .",
@@ -41,6 +43,7 @@
"cross-os": {
"prebuild:desktop": {
"darwin": "cp -r dist/ electron-app/ember-dist/",
+ "linux": "cp -r dist/ electron-app/ember-dist/",
"win32": "(robocopy dist electron-app\\ember-dist /MIR) ^& exit 0"
}
},
diff --git a/ui/desktop/tests/acceptance/application-test.js b/ui/desktop/tests/acceptance/application-test.js
new file mode 100644
index 000000000..23a254e0e
--- /dev/null
+++ b/ui/desktop/tests/acceptance/application-test.js
@@ -0,0 +1,67 @@
+import { module, test } from 'qunit';
+import {
+ visit,
+ // currentURL,
+ // fillIn,
+ // click,
+ find,
+ //findAll,
+ //getRootElement
+ //setupOnerror,
+} from '@ember/test-helpers';
+import { setupApplicationTest } from 'ember-qunit';
+import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
+// import { Response } from 'miragejs';
+// import a11yAudit from 'ember-a11y-testing/test-support/audit';
+import sinon from 'sinon';
+import {
+ // currentSession,
+ // authenticateSession,
+ invalidateSession,
+} from 'ember-simple-auth/test-support';
+import { setupBrowserFakes } from 'ember-browser-services/test-support';
+
+module('Acceptance | origin', function (hooks) {
+ setupApplicationTest(hooks);
+ setupBrowserFakes(hooks, { window: true });
+ setupMirage(hooks);
+
+ const stubs = {
+ ipcService: null,
+ };
+
+ const urls = {
+ origin: null,
+ };
+
+ hooks.beforeEach(function () {
+ invalidateSession();
+
+ urls.origin = '/origin';
+
+ const ipcService = this.owner.lookup('service:ipc');
+ stubs.ipcService = sinon.stub(ipcService, 'invoke');
+ });
+
+ hooks.afterEach(function () {
+ sinon.restore();
+ });
+
+ test('visiting index on MacOS hides custom window actions', async function (assert) {
+ assert.expect(3);
+ stubs.ipcService.withArgs('isMacOS').returns(true);
+ await visit(urls.origin);
+ assert.notOk(find('.button-window-close'));
+ assert.notOk(find('.button-window-minimize'));
+ assert.notOk(find('.button-window-fullscreen'));
+ });
+
+ test('visiting index on non-MacOS shows custom window actions', async function (assert) {
+ assert.expect(3);
+ stubs.ipcService.withArgs('isMacOS').returns(false);
+ await visit(urls.origin);
+ assert.ok(find('.button-window-close'));
+ assert.ok(find('.button-window-minimize'));
+ assert.ok(find('.button-window-fullscreen'));
+ });
+});
diff --git a/ui/desktop/tests/acceptance/targets-test.js b/ui/desktop/tests/acceptance/targets-test.js
index f92168c3a..1e8967543 100644
--- a/ui/desktop/tests/acceptance/targets-test.js
+++ b/ui/desktop/tests/acceptance/targets-test.js
@@ -12,8 +12,8 @@ import {
import { run, later } from '@ember/runloop';
import { setupApplicationTest } from 'ember-qunit';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
-//import { Response } from 'miragejs';
-//import a11yAudit from 'ember-a11y-testing/test-support/audit';
+// import { Response } from 'miragejs';
+import a11yAudit from 'ember-a11y-testing/test-support/audit';
import {
currentSession,
authenticateSession,
@@ -43,8 +43,6 @@ module('Acceptance | targets', function (hooks) {
};
const urls = {
- index: '/',
- origin: '/origin',
scopes: {
global: null,
org: null,
@@ -113,7 +111,7 @@ module('Acceptance | targets', function (hooks) {
invalidateSession();
assert.expect(2);
await visit(urls.targets);
- //await a11yAudit();
+ await a11yAudit();
assert.notOk(currentSession().isAuthenticated);
assert.equal(currentURL(), urls.authenticate.methods.global);
});
@@ -123,11 +121,11 @@ module('Acceptance | targets', function (hooks) {
// This later/cancelTimers technique allows us to test a page with
// active polling. Normally an acceptance test waits for all runloop timers
// to stop before returning from an awaited test, but polling means that
- // runloop timers exist indefinitely. We thus schedule a cancelation before
+ // runloop timers exist indefinitely. We thus schedule a cancellation before
// proceeding with our tests.
later(async () => {
run.cancelTimers();
- //await a11yAudit();
+ await a11yAudit();
assert.equal(currentURL(), urls.targets);
}, 750);
await visit(urls.targets);
diff --git a/ui/desktop/tests/helpers/window-mock-ipc.js b/ui/desktop/tests/helpers/window-mock-ipc.js
index 18195accb..8151c8cbc 100644
--- a/ui/desktop/tests/helpers/window-mock-ipc.js
+++ b/ui/desktop/tests/helpers/window-mock-ipc.js
@@ -18,7 +18,6 @@ class MockIPC {
resetOrigin() {}
isMacOS() {}
- isWindowsOS() {}
}
/**