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/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 c6f7f90bb..7d0cf09d3 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. | @@ -82,11 +83,11 @@ These environment variables may be used to customized the build. | Variable | Description | | -------- | ----------- | -| `BYPASS_CLI_SETUP` | Set to `true` to launch without bootstrapping the CLI (see above). | | `DEBUG_APP_UPDATER` | Enable to debug app updater feature. Must be enabled for all `APP_UPDATER_*` variables to be used. | | `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` | Enable to disallow download and extraction of cli. For development use only. | ### Building for Production @@ -100,7 +101,7 @@ 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 @@ -111,6 +112,14 @@ bypass the download of the CLI, which can be useful for pre-release testing. See [Developing Using Non-Release Versions of Boundary](#developing-using-non-release-versions-of-boundary) for more details. +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() {} } /**