fixed members login and permissions issues
This commit is contained in:
@@ -6,7 +6,7 @@ import { getHomeDir } from '@@/data-path';
|
||||
import { syncUserPiConfig } from '@@/api/server-settings/sync-user-pi-config';
|
||||
import { officerdb, Users } from 'officerdb';
|
||||
|
||||
type WSData = { userId: number; email: string; role: string; sandboxed: boolean; sessionId?: string; cwd?: string; cols?: number; rows?: number };
|
||||
type WSData = { userId: number; email: string; username: string; role: string; sandboxed: boolean; sessionId?: string; cwd?: string; cols?: number; rows?: number };
|
||||
type ShellInfo = { command: string; args: string[]; name: string };
|
||||
type BridgeSession = {
|
||||
client: ServerWebSocket<WSData>;
|
||||
@@ -101,7 +101,7 @@ const ensureDockerImage = () => {
|
||||
dockerImageReady = true;
|
||||
};
|
||||
|
||||
const startDockerSidecar = (port: number, homeDir: string, userId: number, email: string): { dockerId: string } => {
|
||||
const startDockerSidecar = (port: number, homeDir: string, userId: number, username: string): { dockerId: string } => {
|
||||
ensureDockerImage();
|
||||
const dockerPath = Bun.which('docker') ?? 'docker';
|
||||
const dockerId = `officer-terminal-${userId}`;
|
||||
@@ -112,7 +112,6 @@ const startDockerSidecar = (port: number, homeDir: string, userId: number, email
|
||||
Bun.spawnSync({ cmd: [dockerPath, 'rm', '-f', dockerId], stdout: 'ignore', stderr: 'ignore' });
|
||||
}
|
||||
|
||||
const username = (email.split('@')[0] ?? 'officer').replace(/[^a-z0-9_-]/g, '_').slice(0, 32);
|
||||
let uid = 1000;
|
||||
let gid = 1000;
|
||||
try {
|
||||
@@ -123,6 +122,7 @@ const startDockerSidecar = (port: number, homeDir: string, userId: number, email
|
||||
// fallback to defaults
|
||||
}
|
||||
|
||||
const containerHome = `/home/${username}`;
|
||||
const run = Bun.spawnSync({
|
||||
cmd: [
|
||||
dockerPath,
|
||||
@@ -145,9 +145,9 @@ const startDockerSidecar = (port: number, homeDir: string, userId: number, email
|
||||
'-e',
|
||||
`TERMINAL_GID=${gid}`,
|
||||
'-v',
|
||||
`${homeDir}:/home/officer`,
|
||||
`${homeDir}:${containerHome}`,
|
||||
'-w',
|
||||
'/home/officer',
|
||||
containerHome,
|
||||
tag,
|
||||
],
|
||||
stdout: 'inherit',
|
||||
@@ -210,7 +210,7 @@ const dockerStart = (dockerId: string) => {
|
||||
return result.exitCode === 0;
|
||||
};
|
||||
|
||||
const ensureDockerContainer = async (email: string, userId: number, homeDir: string) => {
|
||||
const ensureDockerContainer = async (email: string, userId: number, homeDir: string, username: string) => {
|
||||
const map = await loadContainerMap();
|
||||
const existing = map[email];
|
||||
if (existing && dockerContainerRunning(existing.dockerId)) return existing;
|
||||
@@ -221,7 +221,7 @@ const ensureDockerContainer = async (email: string, userId: number, homeDir: str
|
||||
}
|
||||
|
||||
const port = existing?.port ?? getAvailablePort(map, userId);
|
||||
const docker = startDockerSidecar(port, homeDir, userId, email);
|
||||
const docker = startDockerSidecar(port, homeDir, userId, username);
|
||||
const next = { userId, email, dockerId: docker.dockerId, port };
|
||||
map[email] = next;
|
||||
await saveContainerMap(map);
|
||||
@@ -269,7 +269,7 @@ const startHostSidecar = async () => {
|
||||
export const initTerminalSidecars = async () => {
|
||||
await startHostSidecar();
|
||||
ensureDockerImage();
|
||||
const users = await officerdb.select({ id: Users.id, email: Users.email }).from(Users);
|
||||
const users = await officerdb.select({ id: Users.id, email: Users.email, username: Users.username }).from(Users);
|
||||
for (const user of users) {
|
||||
const homeDir = getHomeDir(user.email);
|
||||
mkdirSync(dirname(homeDir), { recursive: true });
|
||||
@@ -278,7 +278,7 @@ export const initTerminalSidecars = async () => {
|
||||
await syncUserPiConfig(user.email).catch((err) => {
|
||||
console.error(`[terminal] failed to sync Pi config for ${user.email}:`, err);
|
||||
});
|
||||
await ensureDockerContainer(user.email, user.id, homeDir);
|
||||
await ensureDockerContainer(user.email, user.id, homeDir, user.username ?? user.email.split('@')[0]!);
|
||||
console.log(`[terminal] sidecar ready for ${user.email}`);
|
||||
} catch (err) {
|
||||
console.error(`[terminal] failed to start sidecar for ${user.email}:`, err);
|
||||
@@ -287,7 +287,6 @@ export const initTerminalSidecars = async () => {
|
||||
};
|
||||
|
||||
const containerShell: ShellInfo = { command: '/bin/zsh', args: ['-d', '-i'], name: 'zsh' };
|
||||
const containerHome = '/home/officer';
|
||||
|
||||
const resolveCwd = (home: string, cwd?: string) => {
|
||||
if (!cwd || cwd === '~') return home;
|
||||
@@ -298,7 +297,7 @@ const resolveCwd = (home: string, cwd?: string) => {
|
||||
|
||||
export const terminalWebsocket = {
|
||||
async open(ws: ServerWebSocket<WSData>) {
|
||||
const { email, role, sandboxed } = ws.data;
|
||||
const { email, username, role, sandboxed } = ws.data;
|
||||
|
||||
if (!sandboxed && role !== 'Super Admin') {
|
||||
sendOutput(ws, '\r\n[Permission denied] Host terminal requires Super Admin role.\r\n');
|
||||
@@ -363,7 +362,7 @@ export const terminalWebsocket = {
|
||||
let sidecar: WebSocket | null = null;
|
||||
let info: ContainerInfo | undefined;
|
||||
try {
|
||||
info = await ensureDockerContainer(email, ws.data.userId, cwd);
|
||||
info = await ensureDockerContainer(email, ws.data.userId, cwd, username);
|
||||
sidecar = await connectSidecar(info.port);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to connect terminal sidecar';
|
||||
@@ -396,6 +395,7 @@ export const terminalWebsocket = {
|
||||
}
|
||||
});
|
||||
|
||||
const containerHome = `/home/${username}`;
|
||||
sidecar.send(
|
||||
JSON.stringify({
|
||||
type: 'init',
|
||||
|
||||
Reference in New Issue
Block a user