Skip to content

Commit 4ae38ca

Browse files
committed
chore: get config of school ai control with getAIControlStatus
1 parent 1c4588f commit 4ae38ca

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

src/nls/root/strings.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1715,5 +1715,11 @@ define({
17151715
"LICENSE_ACTIVATE_FAIL": "Failed to activate license",
17161716
"LICENSE_ACTIVATE_FAIL_APPLY": "'Failed to apply license to device'",
17171717
"LICENSE_ENTER_KEY": "Please enter a license key",
1718-
"LICENSE_REAPPLY_TO_DEVICE": "Already activated? Reapply system-wide"
1718+
"LICENSE_REAPPLY_TO_DEVICE": "Already activated? Reapply system-wide",
1719+
// AI CONTROL
1720+
"AI_CONTROL_ALL_ALLOWED_NO_CONFIG": "No AI config file found in system. AI is enabled for all users.",
1721+
"AI_CONTROL_ALL_ALLOWED": "AI is enabled for all users.",
1722+
"AI_CONTROL_USER_ALLOWED": "AI is enabled for user ({0}) but disabled for others",
1723+
"AI_CONTROL_ADMIN_DISABLED": "AI access has been disabled by your system administrator",
1724+
"AI_CONTROL_ADMIN_DISABLED_CONTACT": "AI access has been disabled by your system administrator. Please contact {0} for assistance."
17191725
});

src/services/EntitlementsManager.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ define(function (require, exports, module) {
3131
}
3232

3333
const EventDispatcher = require("utils/EventDispatcher"),
34+
AIControl = require("./ai-control"),
3435
Strings = require("strings");
3536

3637
const MS_IN_DAY = 24 * 60 * 60 * 1000;
@@ -180,6 +181,7 @@ define(function (require, exports, module) {
180181
effectiveEntitlements = null;
181182
EntitlementsManager.trigger(EVENT_ENTITLEMENTS_CHANGED);
182183
});
184+
AIControl.init();
183185
}
184186

185187
// Test-only exports for integration testing

src/services/ai-control.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// SPDX-License-Identifier: AGPL-3.0-only
2+
// Copyright (c) 2021 - present core.ai. All rights reserved.
3+
4+
/**
5+
* This file is only relevant to desktop apps.
6+
*
7+
* AI can be not active in phoenix code either by:
8+
* 1. Schools with admin control. See https://docs.phcode.dev/docs/control-ai
9+
* 2. user is not entitled to ai services by his subscription.
10+
*
11+
* This file only deals with case 1. you should use `EntitlementsManager.js` to resolve the correct AI entitlment,
12+
* which will reconcile 1 and 2 to give you appropriate status.
13+
**/
14+
15+
/*global */
16+
17+
define(function (require, exports, module) {
18+
const KernalModeTrust = window.KernalModeTrust;
19+
if(!KernalModeTrust){
20+
// integrated extensions will have access to kernal mode, but not external extensions
21+
throw new Error("ai-control.js should have access to KernalModeTrust. Cannot boot without trust ring");
22+
}
23+
24+
const NodeUtils = require("utils/NodeUtils"),
25+
Strings = require("strings"),
26+
StringUtils = require("utils/StringUtils");
27+
let EntitlementsManager;
28+
29+
/**
30+
* Get the platform-specific config file path
31+
* @returns {string} The path to the config file
32+
*/
33+
function _getAIConfigFilePath() {
34+
let aiConfigPath;
35+
// The path is decided by https://github.com/phcode-dev/phoenix-code-ai-control/tree/main/install_scripts
36+
37+
if(!Phoenix.isNativeApp) {
38+
return "";
39+
}
40+
41+
if (Phoenix.platform === 'win') {
42+
aiConfigPath = 'C:\\Program Files\\Phoenix AI Control\\config.json';
43+
} else if (Phoenix.platform === 'mac') {
44+
aiConfigPath = '/Library/Application Support/Phoenix AI Control/config.json';
45+
} else if (Phoenix.platform === 'linux') {
46+
aiConfigPath = '/etc/phoenix-ai-control/config.json';
47+
} else {
48+
throw new Error(`Unsupported platform: ${Phoenix.platform}`);
49+
}
50+
return Phoenix.VFS.getTauriVirtualPath(aiConfigPath);
51+
}
52+
const AI_CONFIG_FILE_PATH = _getAIConfigFilePath();
53+
if(Phoenix.isNativeApp) {
54+
console.log("AI system Config File is: ", AI_CONFIG_FILE_PATH);
55+
}
56+
57+
/**
58+
* Check if the current user is in the allowed users list
59+
* @param {Array<string>} allowedUsers - List of allowed usernames
60+
* @param {string} currentUser to check against
61+
* @returns {boolean} True if current user is allowed
62+
*/
63+
function _isCurrentUserAllowed(allowedUsers, currentUser) {
64+
if (!allowedUsers || !Array.isArray(allowedUsers) || allowedUsers.length === 0) {
65+
return false;
66+
}
67+
68+
return allowedUsers.includes(currentUser);
69+
}
70+
71+
/**
72+
* Get AI control configuration
73+
* @returns {Object} The configuration status and details
74+
*/
75+
async function getAIControlStatus() {
76+
try {
77+
if(!Phoenix.isNativeApp) {
78+
return {aiEnabled: true}; // AI control with system files in not available in browser.
79+
// In browser, AI can be disabled with firewall only.
80+
}
81+
const fileData = await Phoenix.VFS.readFileResolves(AI_CONFIG_FILE_PATH, 'utf8');
82+
83+
if (fileData.error || !fileData.data) {
84+
return {
85+
aiEnabled: true,
86+
message: Strings.AI_CONTROL_ALL_ALLOWED_NO_CONFIG
87+
}; // No ai config file exists
88+
}
89+
90+
const aiConfig = JSON.parse(fileData.data);
91+
const currentUser = await NodeUtils.getOSUserName();
92+
93+
// Check if AI is disabled globally
94+
if (aiConfig.disableAI === true) {
95+
// Check if current user is in allowed users list
96+
if (aiConfig.allowedUsers && _isCurrentUserAllowed(aiConfig.allowedUsers, currentUser)) {
97+
return {
98+
aiEnabled: true,
99+
message: StringUtils.format(Strings.AI_CONTROL_USER_ALLOWED, currentUser)
100+
};
101+
} else if(aiConfig.managedByEmail){
102+
return {
103+
aiEnabled: false,
104+
message: StringUtils.format(Strings.AI_CONTROL_ADMIN_DISABLED_CONTACT, aiConfig.managedByEmail)
105+
};
106+
}
107+
return {
108+
aiEnabled: false,
109+
message: Strings.AI_CONTROL_ADMIN_DISABLED
110+
};
111+
}
112+
// AI is enabled globally
113+
return {
114+
aiEnabled: true,
115+
message: Strings.AI_CONTROL_ALL_ALLOWED
116+
};
117+
} catch (error) {
118+
console.error('Error checking AI control:', error);
119+
return {aiEnabled: true, message: error.message};
120+
}
121+
}
122+
123+
let inited = false;
124+
function init() {
125+
if(inited){
126+
return;
127+
}
128+
inited = true;
129+
EntitlementsManager = KernalModeTrust.EntitlementsManager;
130+
EntitlementsManager.getAIControlStatus = getAIControlStatus;
131+
}
132+
133+
exports.init = init;
134+
});

0 commit comments

Comments
 (0)