Skip to content

Commit cf8dbed

Browse files
committed
chore: sending device license if configured, non logged in bugs present
1 parent 9e82873 commit cf8dbed

File tree

3 files changed

+87
-54
lines changed

3 files changed

+87
-54
lines changed

src/services/login-service.js

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*/
1818

19-
/*global path*/
19+
/*global path, logger*/
2020

2121
/**
2222
* Shared Login Service
@@ -29,11 +29,16 @@ define(function (require, exports, module) {
2929
require("./setup-login-service"); // this adds loginService to KernalModeTrust
3030
require("./promotions");
3131
require("./login-utils");
32+
const NodeUtils = require("utils/NodeUtils"),
33+
PreferencesManager = require("preferences/PreferencesManager");
3234
const EntitlementsDirectImport = require("./EntitlementsManager"); // this adds Entitlements to KernalModeTrust
3335

3436
const Metrics = require("utils/Metrics"),
3537
Strings = require("strings");
3638

39+
const PREF_STATE_LICENSED_DEVICE_CHECK = "LICENSED_DEVICE_CHECK";
40+
PreferencesManager.stateManager.definePreference(PREF_STATE_LICENSED_DEVICE_CHECK, "boolean", false);
41+
3742
const MS_IN_DAY = 10 * 24 * 60 * 60 * 1000;
3843
const TEN_MINUTES = 10 * 60 * 1000;
3944
const FREE_PLAN_VALIDITY_DAYS = 10000;
@@ -211,6 +216,34 @@ define(function (require, exports, module) {
211216
}
212217
}
213218

219+
async function _getLinuxDeviceID() {
220+
const LINUX_DEVICE_ID_FILE = Phoenix.VFS.getTauriVirtualPath('/etc/machine-id');
221+
const result = await Phoenix.VFS.readFileResolves(LINUX_DEVICE_ID_FILE, 'utf8');
222+
if(result.error || !result.data) {
223+
logger.reportError(result.error, `Failed to read machine-id file for licensing`);
224+
return null;
225+
}
226+
return KernalModeTrust.generateDataSignature(result.data.trim()); // \n and spaces are trimmed, just id please
227+
}
228+
229+
let deviceIDCached = null;
230+
async function getDeviceID() {
231+
if(!Phoenix.isNativeApp) {
232+
// We only grant device licenses to desktop apps. Browsers cannot be uniquely device identified obviously.
233+
return null;
234+
}
235+
if(deviceIDCached) {
236+
return deviceIDCached;
237+
}
238+
switch (Phoenix.platform) {
239+
case 'linux': deviceIDCached = await _getLinuxDeviceID();
240+
}
241+
return deviceIDCached;
242+
}
243+
244+
245+
let deviceLicensePrimed = false,
246+
licencedDeviceCredsAvailable = false;
214247

215248
/**
216249
* Get entitlements from API or disc cache.
@@ -219,8 +252,14 @@ define(function (require, exports, module) {
219252
* Returns null if the user is not logged in
220253
*/
221254
async function getEntitlements(forceRefresh = false) {
255+
if(!deviceLicensePrimed) {
256+
deviceLicensePrimed = true;
257+
// we cache this as device license is only checked at app start. As invoves some files in system loactions,
258+
// we dont want file access errors to happen on every entitlement check.
259+
licencedDeviceCredsAvailable = await isLicensedDevice();
260+
}
222261
// Return null if not logged in
223-
if (!LoginService.isLoggedIn()) {
262+
if (!LoginService.isLoggedIn() && !licencedDeviceCredsAvailable) {
224263
return null;
225264
}
226265

@@ -254,7 +293,10 @@ define(function (require, exports, module) {
254293
const language = brackets.getLocale();
255294
const currentVersion = window.AppConfig.apiVersion || "1.0.0";
256295
let url = `${accountBaseURL}/getAppEntitlements?lang=${language}&version=${currentVersion}`+
257-
`&platform=${Phoenix.platform}&appType=${Phoenix.isNativeApp ? "desktop" : "browser"}}`;
296+
`&platform=${Phoenix.platform}&appType=${Phoenix.isNativeApp ? "desktop" : "browser"}`;
297+
if(licencedDeviceCredsAvailable) {
298+
url += `&deviceID=${await getDeviceID()}`;
299+
}
258300
let fetchOptions = {
259301
method: 'GET',
260302
headers: {
@@ -268,7 +310,7 @@ define(function (require, exports, module) {
268310
const profile = LoginService.getProfile();
269311
if (profile && profile.apiKey && profile.validationCode) {
270312
url += `&appSessionID=${encodeURIComponent(profile.apiKey)}&validationCode=${encodeURIComponent(profile.validationCode)}`;
271-
} else {
313+
} else if(!licencedDeviceCredsAvailable){
272314
console.error('Missing appSessionID or validationCode for desktop app entitlements');
273315
return null;
274316
}
@@ -596,11 +638,43 @@ define(function (require, exports, module) {
596638
};
597639
}
598640

641+
async function addDeviceLicense() {
642+
deviceLicensePrimed = false;
643+
PreferencesManager.stateManager.set(PREF_STATE_LICENSED_DEVICE_CHECK, true);
644+
return NodeUtils.addDeviceLicenseSystemWide();
645+
}
646+
647+
async function removeDeviceLicense() {
648+
deviceLicensePrimed = false;
649+
PreferencesManager.stateManager.set(PREF_STATE_LICENSED_DEVICE_CHECK, false);
650+
return NodeUtils.removeDeviceLicenseSystemWide();
651+
}
652+
653+
async function isLicensedDeviceSystemWide() {
654+
return NodeUtils.isLicensedDeviceSystemWide();
655+
}
656+
657+
/**
658+
* Checks if app is configured to check for device licenses at app start at system or user level.
659+
*
660+
* @returns {Promise<boolean>} - Resolves with `true` if the device is licensed, `false` otherwise.
661+
*/
662+
async function isLicensedDevice() {
663+
const userCheck = PreferencesManager.stateManager.get(PREF_STATE_LICENSED_DEVICE_CHECK);
664+
const systemCheck = await isLicensedDeviceSystemWide();
665+
return userCheck || systemCheck;
666+
}
667+
599668
// Add functions to secure exports
600669
LoginService.getEntitlements = getEntitlements;
601670
LoginService.getEffectiveEntitlements = getEffectiveEntitlements;
602671
LoginService.clearEntitlements = clearEntitlements;
603672
LoginService.getSalt = getSalt;
673+
LoginService.addDeviceLicense = addDeviceLicense;
674+
LoginService.removeDeviceLicense = removeDeviceLicense;
675+
LoginService.isLicensedDevice = isLicensedDevice;
676+
LoginService.isLicensedDeviceSystemWide = isLicensedDeviceSystemWide;
677+
LoginService.getDeviceID = getDeviceID;
604678
LoginService.EVENT_ENTITLEMENTS_CHANGED = EVENT_ENTITLEMENTS_CHANGED;
605679

606680
let inited = false;

src/services/manage-licenses.js

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,35 +33,13 @@ define(function (require, exports, module) {
3333
}
3434

3535
const Strings = require("strings"),
36-
NodeUtils = require("utils/NodeUtils"),
3736
Dialogs = require("widgets/Dialogs"),
3837
Mustache = require("thirdparty/mustache/mustache"),
3938
licenseManagementHTML = require("text!./html/license-management.html");
4039

4140
// Save a copy of window.fetch so that extensions won't tamper with it
4241
let fetchFn = window.fetch;
4342

44-
async function _getLinuxDeviceID() {
45-
const LINUX_DEVICE_ID_FILE = Phoenix.VFS.getTauriVirtualPath('/etc/machine-id');
46-
const result = await Phoenix.VFS.readFileResolves(LINUX_DEVICE_ID_FILE, 'utf8');
47-
if(result.error || !result.data) {
48-
logger.reportError(result.error, `Failed to read machine-id file for licensing`);
49-
return null;
50-
}
51-
return KernalModeTrust.generateDataSignature(result.data.trim()); // \n and spaces are trimmed, just id please
52-
}
53-
54-
async function _getDeviceID() {
55-
if(!Phoenix.isNativeApp) {
56-
// We only grant device licenses to desktop apps. Browsers cannot be uniquely device identified obviously.
57-
return null;
58-
}
59-
switch (Phoenix.platform) {
60-
case 'linux': return _getLinuxDeviceID();
61-
default: return null;
62-
}
63-
}
64-
6543
/**
6644
* Get the API base URL for license operations
6745
*/
@@ -170,7 +148,7 @@ define(function (require, exports, module) {
170148
$valid.show();
171149

172150
// Show reapply button if license is valid but not applied system-wide
173-
const isLicensed = await NodeUtils.isLicensedDeviceSystemWide();
151+
const isLicensed = await KernalModeTrust.loginService.isLicensedDeviceSystemWide();
174152
if (!isLicensed) {
175153
$reapplyContainer.show();
176154
}
@@ -216,7 +194,7 @@ define(function (require, exports, module) {
216194
*/
217195
async function _loadLicenseStatus($dialog) {
218196
try {
219-
const deviceID = await _getDeviceID();
197+
const deviceID = await KernalModeTrust.loginService.getDeviceID();
220198
if (!deviceID) {
221199
_updateLicenseStatusDisplay($dialog, { isValid: false });
222200
return;
@@ -244,7 +222,7 @@ define(function (require, exports, module) {
244222
$btnText.hide();
245223
$btnSpinner.show();
246224

247-
const deviceID = await _getDeviceID();
225+
const deviceID = await KernalModeTrust.loginService.getDeviceID();
248226
if (!deviceID) {
249227
throw new Error('Unable to get device ID. Device licenses are only supported on desktop applications.');
250228
}
@@ -255,7 +233,7 @@ define(function (require, exports, module) {
255233
const result = await _registerDevice(licenseKey, deviceID, platform, deviceLabel);
256234

257235
if (result.isSuccess) {
258-
const addSuccess = await NodeUtils.addDeviceLicense();
236+
const addSuccess = await KernalModeTrust.loginService.addDeviceLicense();
259237
const successString = addSuccess ?
260238
Strings.LICENSE_ACTIVATE_SUCCESS : Strings.LICENSE_ACTIVATE_SUCCESS_PARTIAL;
261239
_showActivationMessage($dialog, true, successString);
@@ -290,7 +268,7 @@ define(function (require, exports, module) {
290268
$link.html('<i class="fa fa-spinner fa-spin" style="margin-right: 6px;"></i>Applying...');
291269
$link.css('pointer-events', 'none');
292270

293-
const addSuccess = await NodeUtils.addDeviceLicense();
271+
const addSuccess = await KernalModeTrust.loginService.addDeviceLicense();
294272
if (addSuccess) {
295273
_showActivationMessage($dialog, true, Strings.LICENSE_ACTIVATE_SUCCESS);
296274
// Refresh license status

src/utils/NodeUtils.js

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,9 @@
2929

3030
define(function (require, exports, module) {
3131
const Strings = require("strings"),
32-
PreferencesManager = require("preferences/PreferencesManager"),
3332
NodeConnector = require('NodeConnector');
3433
const UTILS_NODE_CONNECTOR = "ph_utils";
3534

36-
const PREF_STATE_LICENSED_DEVICE_CHECK = "LICENSED_DEVICE_CHECK";
37-
3835
let utilsConnector;
3936
if(Phoenix.isNativeApp) {
4037
// node not available in browser builds!
@@ -201,12 +198,11 @@ define(function (require, exports, module) {
201198
* @returns {Promise<boolean>} - Resolves true if system wide defile file added, else false.
202199
* @throws {Error} - If called from the browser
203200
*/
204-
async function addDeviceLicense() {
201+
async function addDeviceLicenseSystemWide() {
205202
if (!Phoenix.isNativeApp) {
206203
throw new Error("addDeviceLicense not available in browser");
207204
}
208205
try {
209-
PreferencesManager.stateManager.set(PREF_STATE_LICENSED_DEVICE_CHECK, true);
210206
await utilsConnector.execPeer("addDeviceLicense");
211207
return true;
212208
} catch (err) {
@@ -222,12 +218,11 @@ define(function (require, exports, module) {
222218
* @returns {Promise<boolean>} - Resolves true if system wide defile file removed, else false.
223219
* @throws {Error} - If called from the browser
224220
*/
225-
async function removeDeviceLicense() {
221+
async function removeDeviceLicenseSystemWide() {
226222
if (!Phoenix.isNativeApp) {
227223
throw new Error("removeDeviceLicense not available in browser");
228224
}
229225
try {
230-
PreferencesManager.stateManager.set(PREF_STATE_LICENSED_DEVICE_CHECK, false);
231226
await utilsConnector.execPeer("removeDeviceLicense");
232227
return true;
233228
} catch (err) {
@@ -255,17 +250,6 @@ define(function (require, exports, module) {
255250
return false;
256251
}
257252

258-
/**
259-
* Checks if app is configured to check for device licenses at app start at system or user level.
260-
*
261-
* @returns {Promise<boolean>} - Resolves with `true` if the device is licensed, `false` otherwise.
262-
*/
263-
async function isLicensedDevice() {
264-
const userCheck = PreferencesManager.stateManager.get(PREF_STATE_LICENSED_DEVICE_CHECK);
265-
const systemCheck = await isLicensedDeviceSystemWide();
266-
return userCheck || systemCheck;
267-
}
268-
269253
if(NodeConnector.isNodeAvailable()) {
270254
// todo we need to update the strings if a user extension adds its translations. Since we dont support
271255
// node extensions for now, should consider when we support node extensions.
@@ -291,8 +275,6 @@ define(function (require, exports, module) {
291275
console.error("Error setting Phoenix.isTestWindowGitHubActions", e);
292276
}
293277

294-
PreferencesManager.stateManager.definePreference(PREF_STATE_LICENSED_DEVICE_CHECK, "boolean", false);
295-
296278
// private apis
297279
exports._loadNodeExtensionModule = _loadNodeExtensionModule;
298280
exports._npmInstallInFolder = _npmInstallInFolder;
@@ -306,9 +288,8 @@ define(function (require, exports, module) {
306288
exports.getEnvironmentVariable = getEnvironmentVariable;
307289
exports.openNativeTerminal = openNativeTerminal;
308290
exports.openInDefaultApp = openInDefaultApp;
309-
exports.addDeviceLicense = addDeviceLicense;
310-
exports.removeDeviceLicense = removeDeviceLicense;
311-
exports.isLicensedDevice = isLicensedDevice;
291+
exports.addDeviceLicenseSystemWide = addDeviceLicenseSystemWide;
292+
exports.removeDeviceLicenseSystemWide = removeDeviceLicenseSystemWide;
312293
exports.isLicensedDeviceSystemWide = isLicensedDeviceSystemWide;
313294

314295
/**

0 commit comments

Comments
 (0)