Skip to content

Commit 57b424e

Browse files
authored
Merge pull request #1348 from trycompai/main
[comp] Production Deploy
2 parents 18a4d94 + 9db9538 commit 57b424e

File tree

16 files changed

+507
-204
lines changed

16 files changed

+507
-204
lines changed

apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/Employee.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ interface EmployeeDetailsProps {
1616
})[];
1717
fleetPolicies: FleetPolicy[];
1818
host: Host;
19-
isFleetEnabled: boolean;
2019
}
2120

2221
export function Employee({
@@ -25,7 +24,6 @@ export function Employee({
2524
trainingVideos,
2625
fleetPolicies,
2726
host,
28-
isFleetEnabled,
2927
}: EmployeeDetailsProps) {
3028
return (
3129
<div className="flex flex-col gap-4">
@@ -36,7 +34,6 @@ export function Employee({
3634
trainingVideos={trainingVideos}
3735
fleetPolicies={fleetPolicies}
3836
host={host}
39-
isFleetEnabled={isFleetEnabled}
4037
/>
4138
</div>
4239
);

apps/app/src/app/(app)/[orgId]/people/[employeeId]/components/EmployeeTasks.tsx

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export const EmployeeTasks = ({
1313
trainingVideos,
1414
host,
1515
fleetPolicies,
16-
isFleetEnabled,
1716
}: {
1817
employee: Member & {
1918
user: User;
@@ -24,7 +23,6 @@ export const EmployeeTasks = ({
2423
})[];
2524
host: Host;
2625
fleetPolicies: FleetPolicy[];
27-
isFleetEnabled: boolean;
2826
}) => {
2927
return (
3028
<Card>
@@ -43,7 +41,7 @@ export const EmployeeTasks = ({
4341
<TabsList className="mb-4">
4442
<TabsTrigger value="policies">Policies</TabsTrigger>
4543
<TabsTrigger value="training">Training Videos</TabsTrigger>
46-
{isFleetEnabled && <TabsTrigger value="device">Device</TabsTrigger>}
44+
<TabsTrigger value="device">Device</TabsTrigger>
4745
</TabsList>
4846

4947
<TabsContent value="policies">
@@ -116,45 +114,43 @@ export const EmployeeTasks = ({
116114
</div>
117115
</TabsContent>
118116

119-
{isFleetEnabled && (
120-
<TabsContent value="device">
121-
{host ? (
122-
<Card>
123-
<CardHeader>
124-
<CardTitle>{host.computer_name}'s Policies</CardTitle>
125-
</CardHeader>
126-
<CardContent className="space-y-3">
127-
{fleetPolicies.map((policy) => (
128-
<div
129-
key={policy.id}
130-
className={cn(
131-
'hover:bg-muted/50 flex items-center justify-between rounded-md border border-l-4 p-3 shadow-sm transition-colors',
132-
policy.response === 'pass' ? 'border-l-green-500' : 'border-l-red-500',
133-
)}
134-
>
135-
<p className="font-medium">{policy.name}</p>
136-
{policy.response === 'pass' ? (
137-
<div className="flex items-center gap-1 text-green-600">
138-
<CheckCircle2 size={16} />
139-
<span>Pass</span>
140-
</div>
141-
) : (
142-
<div className="flex items-center gap-1 text-red-600">
143-
<XCircle size={16} />
144-
<span>Fail</span>
145-
</div>
146-
)}
147-
</div>
148-
))}
149-
</CardContent>
150-
</Card>
151-
) : (
152-
<div className="text-muted-foreground py-6 text-center">
153-
<p>No device found.</p>
154-
</div>
155-
)}
156-
</TabsContent>
157-
)}
117+
<TabsContent value="device">
118+
{host ? (
119+
<Card>
120+
<CardHeader>
121+
<CardTitle>{host.computer_name}'s Policies</CardTitle>
122+
</CardHeader>
123+
<CardContent className="space-y-3">
124+
{fleetPolicies.map((policy) => (
125+
<div
126+
key={policy.id}
127+
className={cn(
128+
'hover:bg-muted/50 flex items-center justify-between rounded-md border border-l-4 p-3 shadow-sm transition-colors',
129+
policy.response === 'pass' ? 'border-l-green-500' : 'border-l-red-500',
130+
)}
131+
>
132+
<p className="font-medium">{policy.name}</p>
133+
{policy.response === 'pass' ? (
134+
<div className="flex items-center gap-1 text-green-600">
135+
<CheckCircle2 size={16} />
136+
<span>Pass</span>
137+
</div>
138+
) : (
139+
<div className="flex items-center gap-1 text-red-600">
140+
<XCircle size={16} />
141+
<span>Fail</span>
142+
</div>
143+
)}
144+
</div>
145+
))}
146+
</CardContent>
147+
</Card>
148+
) : (
149+
<div className="text-muted-foreground py-6 text-center">
150+
<p>No device found.</p>
151+
</div>
152+
)}
153+
</TabsContent>
158154
</Tabs>
159155
</CardContent>
160156
</Card>

apps/app/src/app/(app)/[orgId]/people/[employeeId]/page.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { auth } from '@/utils/auth';
22

3-
import { getPostHogClient } from '@/app/posthog';
43
import {
54
type TrainingVideo,
65
trainingVideos as trainingVideosData,
@@ -40,10 +39,6 @@ export default async function EmployeeDetailsPage({
4039
}
4140

4241
const { fleetPolicies, device } = await getFleetPolicies(employee);
43-
const isFleetEnabled = await getPostHogClient()?.isFeatureEnabled(
44-
'is-fleet-enabled',
45-
session?.session.userId,
46-
);
4742

4843
return (
4944
<Employee
@@ -52,7 +47,6 @@ export default async function EmployeeDetailsPage({
5247
trainingVideos={employeeTrainingVideos}
5348
fleetPolicies={fleetPolicies}
5449
host={device}
55-
isFleetEnabled={isFleetEnabled ?? false}
5650
/>
5751
);
5852
}

apps/app/src/app/(app)/[orgId]/people/layout.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getPostHogClient } from '@/app/posthog';
21
import { auth } from '@/utils/auth';
32
import { SecondaryMenu } from '@comp/ui/secondary-menu';
43
import { db } from '@db';
@@ -27,11 +26,6 @@ export default async function Layout({ children }: { children: React.ReactNode }
2726
return roles.includes('employee');
2827
});
2928

30-
const isFleetEnabled = await getPostHogClient()?.isFeatureEnabled(
31-
'is-fleet-enabled',
32-
session?.session.userId,
33-
);
34-
3529
return (
3630
<div className="m-auto max-w-[1200px]">
3731
<SecondaryMenu
@@ -48,14 +42,10 @@ export default async function Layout({ children }: { children: React.ReactNode }
4842
},
4943
]
5044
: []),
51-
...(isFleetEnabled
52-
? [
53-
{
54-
path: `/${orgId}/people/devices`,
55-
label: 'Employee Devices',
56-
},
57-
]
58-
: []),
45+
{
46+
path: `/${orgId}/people/devices`,
47+
label: 'Employee Devices',
48+
},
5949
]}
6050
/>
6151

apps/app/src/jobs/tasks/device/create-fleet-label-for-org.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,21 @@ export const createFleetLabelForOrg = task({
2929
return;
3030
}
3131

32-
const fleetDevicePathMac = process.env.FLEET_DEVICE_PATH_MAC;
33-
const fleetDevicePathWindows = process.env.FLEET_DEVICE_PATH_WINDOWS;
32+
const fleetDevicePathMac = '/Users/Shared/.fleet';
33+
const fleetDevicePathWindows = 'C:\\ProgramData\\CompAI\\Fleet';
34+
const windowsFallbackDir = 'C:\\Users\\Public\\CompAI\\Fleet';
3435

35-
if (!fleetDevicePathMac || !fleetDevicePathWindows) {
36-
logger.error('FLEET_DEVICE_PATH_MAC or FLEET_DEVICE_PATH_WINDOWS not configured');
37-
return;
38-
}
39-
40-
// Create a query that matches devices from either macOS or Windows
41-
const query = `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}' OR path = '${fleetDevicePathWindows}\\${organizationId}' LIMIT 1;`;
36+
// Simple union query: only file table, constrained per platform path
37+
const query = `
38+
SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${organizationId}'
39+
UNION SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${organizationId}'
40+
UNION SELECT 1 FROM file WHERE path = '${windowsFallbackDir}\\${organizationId}'
41+
LIMIT 1;`;
42+
const normalizedQuery = query.replace(/\s+/g, ' ').trim();
4243

4344
logger.info('Creating label', {
4445
name: organization.id,
45-
query: query,
46+
query: normalizedQuery,
4647
});
4748

4849
const fleet = await getFleetInstance();
@@ -53,7 +54,7 @@ export const createFleetLabelForOrg = task({
5354
// Create a manual label that we can assign to hosts.
5455
labelResponse = await fleet.post('/labels', {
5556
name: organization.id,
56-
query: query,
57+
query: normalizedQuery,
5758
});
5859

5960
logger.info('Label created', {

apps/portal/src/app/(app)/(home)/[orgId]/components/EmployeeTasksList.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ interface EmployeeTasksListProps {
1515
member: Member;
1616
fleetPolicies: FleetPolicy[];
1717
host: Host | null;
18-
isFleetEnabled: boolean;
1918
}
2019

2120
export const EmployeeTasksList = ({
@@ -24,7 +23,6 @@ export const EmployeeTasksList = ({
2423
member,
2524
fleetPolicies,
2625
host,
27-
isFleetEnabled,
2826
}: EmployeeTasksListProps) => {
2927
// Check completion status
3028
const hasAcceptedPolicies =
@@ -58,16 +56,12 @@ export const EmployeeTasksList = ({
5856
title: 'Accept security policies',
5957
content: <PoliciesAccordionItem policies={policies} member={member} />,
6058
},
61-
...(isFleetEnabled
62-
? [
63-
{
64-
title: 'Download and install Comp AI Device Agent',
65-
content: (
66-
<DeviceAgentAccordionItem member={member} host={host} fleetPolicies={fleetPolicies} />
67-
),
68-
},
69-
]
70-
: []),
59+
{
60+
title: 'Download and install Comp AI Device Agent',
61+
content: (
62+
<DeviceAgentAccordionItem member={member} host={host} fleetPolicies={fleetPolicies} />
63+
),
64+
},
7165
{
7266
title: 'Complete general security awareness training',
7367
content: <GeneralTrainingAccordionItem trainingVideoCompletions={trainingVideoCompletions} />,

apps/portal/src/app/(app)/(home)/[orgId]/components/OrganizationDashboard.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ interface OrganizationDashboardProps {
1515
member: MemberWithUserOrg; // Pass the full member object for user info etc.
1616
fleetPolicies: FleetPolicy[];
1717
host: Host | null;
18-
isFleetEnabled: boolean;
1918
}
2019

2120
export async function OrganizationDashboard({
2221
organizationId,
2322
member,
2423
fleetPolicies,
2524
host,
26-
isFleetEnabled,
2725
}: OrganizationDashboardProps) {
2826
// Fetch policies specific to the selected organization
2927
const policies = await db.policy.findMany({
@@ -74,7 +72,6 @@ export async function OrganizationDashboard({
7472
member={member} // Pass the member object down
7573
fleetPolicies={fleetPolicies}
7674
host={host}
77-
isFleetEnabled={isFleetEnabled ?? false}
7875
/>
7976
);
8077
}

apps/portal/src/app/(app)/(home)/[orgId]/page.tsx

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use server';
22

33
import { auth } from '@/app/lib/auth';
4-
import { getPostHogClient } from '@/app/posthog';
54
import { getFleetInstance } from '@/utils/fleet';
65
import type { Member } from '@db';
76
import { db } from '@db';
@@ -45,26 +44,13 @@ export default async function OrganizationPage({ params }: { params: Promise<{ o
4544
return redirect('/'); // Or appropriate login/auth route
4645
}
4746

48-
// Check fleet feature flag first
49-
let isFleetEnabled = false;
50-
try {
51-
const postHogClient = await getPostHogClient();
52-
isFleetEnabled =
53-
(await postHogClient?.isFeatureEnabled('is-fleet-enabled', session?.user.id)) ?? false;
54-
} catch (error) {
55-
console.error('Error checking fleet feature flag:', error);
56-
// Default to false if there's an error
57-
}
58-
5947
// Only fetch fleet policies if fleet is enabled
6048
let fleetPolicies: FleetPolicy[] = [];
6149
let device: Host | null = null;
6250

63-
if (isFleetEnabled) {
64-
const fleetData = await getFleetPolicies(member);
65-
fleetPolicies = fleetData.fleetPolicies;
66-
device = fleetData.device;
67-
}
51+
const fleetData = await getFleetPolicies(member);
52+
fleetPolicies = fleetData.fleetPolicies;
53+
device = fleetData.device;
6854

6955
return (
7056
<OrganizationDashboard
@@ -73,7 +59,6 @@ export default async function OrganizationPage({ params }: { params: Promise<{ o
7359
member={member}
7460
fleetPolicies={fleetPolicies}
7561
host={device}
76-
isFleetEnabled={isFleetEnabled}
7762
/>
7863
);
7964
} catch (error) {

apps/portal/src/app/api/download-agent/fleet-label.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,35 @@ export async function createFleetLabel({
2424
const fleet = await getFleetInstance();
2525
logger('Fleet instance obtained successfully');
2626

27-
// Create platform-specific query
27+
// OS-specific queries: mac uses file-only; Windows uses UNION with file and registry
2828
const query =
2929
os === 'macos'
3030
? `SELECT 1 FROM file WHERE path = '${fleetDevicePathMac}/${employeeId}' LIMIT 1;`
31-
: `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}' LIMIT 1;`;
31+
: `SELECT 1 FROM file WHERE path = '${fleetDevicePathWindows}\\${employeeId}'
32+
UNION SELECT 1 FROM file WHERE path = 'C:\\Users\\Public\\CompAI\\Fleet\\${employeeId}'
33+
LIMIT 1;`;
34+
35+
// Normalize whitespace to a single line to avoid issues with newlines/tabs
36+
const normalizedQuery = query.replace(/\s+/g, ' ').trim();
3237

3338
logger('Generated Fleet query for label creation', {
3439
employeeId,
3540
os,
36-
query,
41+
query: normalizedQuery,
3742
});
3843

3944
logger('Sending POST request to Fleet API to create label...', {
4045
labelName: employeeId,
4146
endpoint: '/labels',
4247
requestBody: {
4348
name: employeeId,
44-
query: query,
49+
query: normalizedQuery,
4550
},
4651
});
4752

4853
const response = await fleet.post('/labels', {
4954
name: employeeId,
50-
query: query,
55+
query: normalizedQuery,
5156
});
5257

5358
logger('Fleet API response received', {

0 commit comments

Comments
 (0)