@@ -4,13 +4,10 @@ const fs = require('fs');
44const fsPromise = require ( 'fs' ) . promises ;
55const path = require ( 'path' ) ;
66const os = require ( 'os' ) ;
7- const sudo = require ( '@expo/sudo-prompt' ) ;
8- const { lintFile } = require ( "./ESLint/service " ) ;
7+ const { lintFile } = require ( "./ESLint/service" ) ;
8+ const { addDeviceLicense , getDeviceID , isLicensedDevice , removeDeviceLicense } = require ( "./licence-device " ) ;
99let openModule , open ; // dynamic import when needed
1010
11- const options = { name : 'Phoenix Code' } ;
12- const licenseFileContent = JSON . stringify ( { } ) ;
13-
1411async function _importOpen ( ) {
1512 if ( open ) {
1613 return open ;
@@ -273,174 +270,8 @@ async function getEnvironmentVariable(varName) {
273270 return process . env [ varName ] ;
274271}
275272
276- function getLicensePath ( ) {
277- switch ( os . platform ( ) ) {
278- case 'win32' :
279- return 'C:\\Program Files\\Phoenix Code Control\\device-license' ;
280- case 'darwin' :
281- return '/Library/Application Support/phoenix-code-control/device-license' ;
282- case 'linux' :
283- return '/etc/phoenix-code-control/device-license' ;
284- default :
285- throw new Error ( `Unsupported platform: ${ os . platform ( ) } ` ) ;
286- }
287- }
288-
289- function sudoExec ( command ) {
290- return new Promise ( ( resolve , reject ) => {
291- sudo . exec ( command , options , ( error , stdout , stderr ) => {
292- if ( error ) {
293- return reject ( error ) ;
294- }
295- resolve ( { stdout, stderr } ) ;
296- } ) ;
297- } ) ;
298- }
299-
300- function readFileUtf8 ( p ) {
301- return new Promise ( ( resolve , reject ) => {
302- fs . readFile ( p , 'utf8' , ( err , data ) => ( err ? reject ( err ) : resolve ( data ) ) ) ;
303- } ) ;
304- }
305-
306- /**
307- * Writes the license file in a world-readable location.
308- * Works on Windows, macOS, and Linux.
309- */
310- async function addDeviceLicense ( ) {
311- const targetPath = getLicensePath ( ) ;
312- let command ;
313- // we should not store any sensitive information in this file as this is world readable. we use the
314- // device id itself as license key for that machine. the device id is not associated with any cloud credits
315- // and all entitlements are local to device only for this threat model to work. So stolen device IDs doesn't
316- // have any meaning.
317-
318- if ( os . platform ( ) === 'win32' ) {
319- // Windows: write file and explicitly grant Everyone read rights
320- const dir = 'C:\\Program Files\\Phoenix Code Control' ;
321- command =
322- `powershell -Command "` +
323- `New-Item -ItemType Directory -Force '${ dir } ' | Out-Null; ` +
324- `Set-Content -Path '${ targetPath } ' -Value '${ licenseFileContent } ' -Encoding UTF8; ` +
325- `icacls '${ targetPath } ' /inheritance:e /grant *S-1-1-0:RX | Out-Null"` ;
326- } else {
327- // macOS / Linux: mkdir + write + chmod 0644 (world-readable, owner-writable)
328- const dir = path . dirname ( targetPath ) ;
329- command =
330- `/bin/mkdir -p "${ dir } "` +
331- ` && printf '%s' '${ licenseFileContent } ' > "${ targetPath } "` +
332- ` && /bin/chmod 0644 "${ targetPath } "` ;
333- }
334-
335- await sudoExec ( command ) ;
336- return targetPath ;
337- }
338-
339- async function removeDeviceLicense ( ) {
340- const targetPath = getLicensePath ( ) ;
341- let command ;
342-
343- if ( os . platform ( ) === 'win32' ) {
344- command = `powershell -Command "if (Test-Path '${ targetPath } ') { Remove-Item -Path '${ targetPath } ' -Force }"` ;
345- } else {
346- command = `/bin/rm -f "${ targetPath } "` ;
347- }
348-
349- await sudoExec ( command ) ;
350- return targetPath ;
351- }
352-
353- async function isLicensedDevice ( ) {
354- const targetPath = getLicensePath ( ) ;
355- try {
356- const data = await readFileUtf8 ( targetPath ) ;
357- JSON . parse ( data . trim ( ) ) ;
358- return true ; // currently, the existence of the file itself is flag. in future, we may choose to add more.
359- } catch {
360- // file missing, unreadable, or invalid JSON
361- return false ;
362- }
363- }
364-
365- async function _getLinuxDeviceID ( ) {
366- const data = await fsPromise . readFile ( "/etc/machine-id" , "utf8" ) ;
367- const id = data . trim ( ) ;
368- return id || null ;
369- // throw on error to main.
370- // no fallback, /var/lib/dbus/machine-id may need sudo in some machines
371- }
372-
373- /**
374- * Get the macOS device ID (IOPlatformUUID).
375- * @returns {Promise<string|null> }
376- */
377- function _getMacDeviceID ( ) {
378- // to read this in mac bash, do:
379- // #!/bin/bash
380- // device_id=$(ioreg -rd1 -c IOPlatformExpertDevice | awk -F\" '/IOPlatformUUID/ {print $4}' | tr -d '[:space:]')
381- // echo "$device_id"
382- return new Promise ( ( resolve , reject ) => {
383- exec (
384- 'ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID' ,
385- { encoding : 'utf8' } ,
386- ( err , stdout ) => {
387- if ( err ) {
388- console . error ( 'Failed to get Mac device ID:' , err . message ) ;
389- return reject ( err ) ;
390- }
391-
392- const match = stdout . match ( / " I O P l a t f o r m U U I D " = " ( [ ^ " ] + ) " / ) ;
393- if ( match && match [ 1 ] ) {
394- resolve ( match [ 1 ] ) ;
395- } else {
396- resolve ( null ) ;
397- }
398- }
399- ) ;
400- } ) ;
401- }
402-
403- /**
404- * Get the Windows device ID (MachineGuid).
405- * @returns {Promise<string|null> }
406- *
407- * In a Windows batch file, you can get this with:
408- * reg query HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography /v MachineGuid
409- */
410- function _getWindowsDeviceID ( ) {
411- return new Promise ( ( resolve , reject ) => {
412- exec (
413- 'reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography /v MachineGuid' ,
414- { encoding : 'utf8' } ,
415- ( err , stdout ) => {
416- if ( err ) {
417- console . error ( 'Failed to get Windows device ID:' , err . message ) ;
418- return reject ( err ) ;
419- }
420-
421- // Example output:
422- // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
423- // MachineGuid REG_SZ 4c4c4544-0034-5a10-8051-cac04f305a31
424- const match = stdout . match ( / M a c h i n e G u i d \s + R E G _ [ A - Z ] + \s + ( [ a - f A - F 0 - 9 - ] + ) / ) ;
425- if ( match && match [ 1 ] ) {
426- resolve ( match [ 1 ] . trim ( ) ) ;
427- } else {
428- resolve ( null ) ;
429- }
430- }
431- ) ;
432- } ) ;
433- }
434-
435- async function getDeviceID ( ) {
436- if ( process . platform === "linux" ) {
437- return _getLinuxDeviceID ( ) ;
438- } else if ( process . platform === "darwin" ) {
439- return _getMacDeviceID ( ) ;
440- } else if ( process . platform === "win32" ) {
441- return _getWindowsDeviceID ( ) ;
442- }
443- throw new Error ( `Unsupported platform: ${ process . platform } ` ) ;
273+ async function getOSUserName ( ) {
274+ return os . userInfo ( ) . username ;
444275}
445276
446277exports . getURLContent = getURLContent ;
@@ -456,5 +287,6 @@ exports.addDeviceLicense = addDeviceLicense;
456287exports . removeDeviceLicense = removeDeviceLicense ;
457288exports . isLicensedDevice = isLicensedDevice ;
458289exports . getDeviceID = getDeviceID ;
290+ exports . getOSUserName = getOSUserName ;
459291exports . _loadNodeExtensionModule = _loadNodeExtensionModule ;
460292exports . _npmInstallInFolder = _npmInstallInFolder ;
0 commit comments