myaidev-method 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/wordpress-admin.md +271 -0
- package/.env.example +0 -1
- package/COOLIFY_DEPLOYMENT.md +1 -1
- package/DEV_WORKFLOW_GUIDE.md +1 -1
- package/PACKAGE_FIXES_SUMMARY.md +319 -0
- package/PAYLOADCMS_AUTH_UPDATE.md +248 -0
- package/PUBLISHING_GUIDE.md +1 -1
- package/README.md +7 -7
- package/USER_GUIDE.md +261 -1
- package/WORDPRESS_ADMIN_SCRIPTS.md +1 -1
- package/bin/cli.js +36 -0
- package/dist/server/.tsbuildinfo +1 -0
- package/dist/server/auth/controllers/AuthController.d.ts +34 -0
- package/dist/server/auth/controllers/AuthController.d.ts.map +1 -0
- package/dist/server/auth/controllers/AuthController.js +43 -0
- package/dist/server/auth/controllers/AuthController.js.map +1 -0
- package/dist/server/auth/example-usage.d.ts +53 -0
- package/dist/server/auth/example-usage.d.ts.map +1 -0
- package/dist/server/auth/example-usage.js +129 -0
- package/dist/server/auth/example-usage.js.map +1 -0
- package/dist/server/auth/index.d.ts +11 -0
- package/dist/server/auth/index.d.ts.map +1 -0
- package/dist/server/auth/index.js +15 -0
- package/dist/server/auth/index.js.map +1 -0
- package/dist/server/auth/layers.d.ts +19 -0
- package/dist/server/auth/layers.d.ts.map +1 -0
- package/dist/server/auth/layers.js +33 -0
- package/dist/server/auth/layers.js.map +1 -0
- package/dist/server/auth/middleware/authMiddleware.d.ts +24 -0
- package/dist/server/auth/middleware/authMiddleware.d.ts.map +1 -0
- package/dist/server/auth/middleware/authMiddleware.js +65 -0
- package/dist/server/auth/middleware/authMiddleware.js.map +1 -0
- package/dist/server/auth/routes/authRoutes.d.ts +11 -0
- package/dist/server/auth/routes/authRoutes.d.ts.map +1 -0
- package/dist/server/auth/routes/authRoutes.js +213 -0
- package/dist/server/auth/routes/authRoutes.js.map +1 -0
- package/dist/server/auth/services/AuditLogService.d.ts +21 -0
- package/dist/server/auth/services/AuditLogService.d.ts.map +1 -0
- package/dist/server/auth/services/AuditLogService.js +28 -0
- package/dist/server/auth/services/AuditLogService.js.map +1 -0
- package/dist/server/auth/services/AuthService.d.ts +27 -0
- package/dist/server/auth/services/AuthService.d.ts.map +1 -0
- package/dist/server/auth/services/AuthService.js +246 -0
- package/dist/server/auth/services/AuthService.js.map +1 -0
- package/dist/server/auth/services/PasswordService.d.ts +12 -0
- package/dist/server/auth/services/PasswordService.d.ts.map +1 -0
- package/dist/server/auth/services/PasswordService.js +31 -0
- package/dist/server/auth/services/PasswordService.js.map +1 -0
- package/dist/server/auth/services/SessionRepository.d.ts +24 -0
- package/dist/server/auth/services/SessionRepository.d.ts.map +1 -0
- package/dist/server/auth/services/SessionRepository.js +101 -0
- package/dist/server/auth/services/SessionRepository.js.map +1 -0
- package/dist/server/auth/services/TokenService.d.ts +12 -0
- package/dist/server/auth/services/TokenService.d.ts.map +1 -0
- package/dist/server/auth/services/TokenService.js +86 -0
- package/dist/server/auth/services/TokenService.js.map +1 -0
- package/dist/server/auth/services/UserRepository.d.ts +23 -0
- package/dist/server/auth/services/UserRepository.d.ts.map +1 -0
- package/dist/server/auth/services/UserRepository.js +168 -0
- package/dist/server/auth/services/UserRepository.js.map +1 -0
- package/dist/server/auth/services/example.d.ts +26 -0
- package/dist/server/auth/services/example.d.ts.map +1 -0
- package/dist/server/auth/services/example.js +221 -0
- package/dist/server/auth/services/example.js.map +1 -0
- package/dist/server/auth/services/index.d.ts +6 -0
- package/dist/server/auth/services/index.d.ts.map +1 -0
- package/dist/server/auth/services/index.js +7 -0
- package/dist/server/auth/services/index.js.map +1 -0
- package/dist/server/database/db.d.ts +28 -0
- package/dist/server/database/db.d.ts.map +1 -0
- package/dist/server/database/db.js +91 -0
- package/dist/server/database/db.js.map +1 -0
- package/dist/server/database/schema.sql +95 -0
- package/dist/server/hono/app.d.ts +10 -0
- package/dist/server/hono/app.d.ts.map +1 -0
- package/dist/server/hono/app.js +26 -0
- package/dist/server/hono/app.js.map +1 -0
- package/dist/server/hono/routes.d.ts +12 -0
- package/dist/server/hono/routes.d.ts.map +1 -0
- package/dist/server/hono/routes.js +40 -0
- package/dist/server/hono/routes.js.map +1 -0
- package/dist/server/main.d.ts +2 -0
- package/dist/server/main.d.ts.map +1 -0
- package/dist/server/main.js +94 -0
- package/dist/server/main.js.map +1 -0
- package/dist/server/user-management/DirectoryService.d.ts +62 -0
- package/dist/server/user-management/DirectoryService.d.ts.map +1 -0
- package/dist/server/user-management/DirectoryService.js +201 -0
- package/dist/server/user-management/DirectoryService.js.map +1 -0
- package/dist/server/user-management/LinuxUserService.d.ts +71 -0
- package/dist/server/user-management/LinuxUserService.d.ts.map +1 -0
- package/dist/server/user-management/LinuxUserService.js +192 -0
- package/dist/server/user-management/LinuxUserService.js.map +1 -0
- package/dist/server/user-management/QuotaService.d.ts +59 -0
- package/dist/server/user-management/QuotaService.d.ts.map +1 -0
- package/dist/server/user-management/QuotaService.js +148 -0
- package/dist/server/user-management/QuotaService.js.map +1 -0
- package/dist/server/user-management/UserManagementService.d.ts +74 -0
- package/dist/server/user-management/UserManagementService.d.ts.map +1 -0
- package/dist/server/user-management/UserManagementService.js +122 -0
- package/dist/server/user-management/UserManagementService.js.map +1 -0
- package/dist/server/user-management/index.d.ts +26 -0
- package/dist/server/user-management/index.d.ts.map +1 -0
- package/dist/server/user-management/index.js +26 -0
- package/dist/server/user-management/index.js.map +1 -0
- package/dist/server/user-management/layers.d.ts +27 -0
- package/dist/server/user-management/layers.d.ts.map +1 -0
- package/dist/server/user-management/layers.js +37 -0
- package/dist/server/user-management/layers.js.map +1 -0
- package/dist/shared/types.d.ts +94 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +32 -0
- package/dist/shared/types.js.map +1 -0
- package/package.json +26 -6
- package/src/lib/payloadcms-utils.js +5 -12
- package/src/server/auth/ARCHITECTURE.md +575 -0
- package/src/server/auth/IMPLEMENTATION_SUMMARY.md +287 -0
- package/src/server/auth/QUICK_START.md +283 -0
- package/src/server/auth/README.md +290 -0
- package/src/server/auth/controllers/AuthController.ts +129 -0
- package/src/server/auth/example-usage.ts +159 -0
- package/src/server/auth/index.ts +19 -0
- package/src/server/auth/layers.ts +57 -0
- package/src/server/auth/middleware/authMiddleware.ts +118 -0
- package/src/server/auth/routes/authRoutes.ts +319 -0
- package/src/server/auth/services/AuditLogService.ts +81 -0
- package/src/server/auth/services/AuthService.ts +408 -0
- package/src/server/auth/services/IMPLEMENTATION_SUMMARY.md +404 -0
- package/src/server/auth/services/PasswordService.ts +85 -0
- package/src/server/auth/services/README.md +361 -0
- package/src/server/auth/services/SessionRepository.ts +227 -0
- package/src/server/auth/services/TokenService.ts +174 -0
- package/src/server/auth/services/UserRepository.ts +318 -0
- package/src/server/auth/services/example.ts +346 -0
- package/src/server/auth/services/index.ts +6 -0
- package/src/server/database/db.ts +161 -0
- package/src/server/database/schema.sql +95 -0
- package/src/server/hono/app.ts +41 -0
- package/src/server/main.ts +115 -0
- package/src/server/user-management/DirectoryService.ts +348 -0
- package/src/server/user-management/LinuxUserService.ts +338 -0
- package/src/server/user-management/QuotaService.ts +256 -0
- package/src/server/user-management/README.md +333 -0
- package/src/server/user-management/UserManagementService.ts +335 -0
- package/src/server/user-management/index.ts +26 -0
- package/src/server/user-management/layers.ts +51 -0
- package/src/shared/types.ts +111 -0
- package/src/templates/claude/agents/payloadcms-publish.md +34 -14
- package/src/templates/codex/commands/myai-astro-publish.md +8 -2
- package/src/templates/codex/commands/myai-content-writer.md +8 -2
- package/src/templates/codex/commands/myai-coolify-deploy.md +8 -2
- package/src/templates/codex/commands/myai-dev-architect.md +8 -2
- package/src/templates/codex/commands/myai-dev-code.md +8 -2
- package/src/templates/codex/commands/myai-dev-docs.md +8 -2
- package/src/templates/codex/commands/myai-dev-review.md +8 -2
- package/src/templates/codex/commands/myai-dev-test.md +8 -2
- package/src/templates/codex/commands/myai-docusaurus-publish.md +8 -2
- package/src/templates/codex/commands/myai-mintlify-publish.md +8 -2
- package/src/templates/codex/commands/myai-payloadcms-publish.md +17 -3
- package/src/templates/codex/commands/myai-sparc-workflow.md +8 -2
- package/src/templates/codex/commands/myai-wordpress-admin.md +8 -2
- package/src/templates/codex/commands/myai-wordpress-publish.md +8 -2
- package/src/templates/docs/wordpress-troubleshoot.js +2 -2
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
-- Users table
|
|
2
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
username TEXT UNIQUE NOT NULL,
|
|
5
|
+
email TEXT UNIQUE NOT NULL,
|
|
6
|
+
password_hash TEXT,
|
|
7
|
+
linux_username TEXT UNIQUE NOT NULL,
|
|
8
|
+
created_at INTEGER DEFAULT (strftime('%s','now')),
|
|
9
|
+
updated_at INTEGER DEFAULT (strftime('%s','now')),
|
|
10
|
+
is_active INTEGER DEFAULT 1,
|
|
11
|
+
email_verified INTEGER DEFAULT 0,
|
|
12
|
+
failed_login_attempts INTEGER DEFAULT 0,
|
|
13
|
+
last_login_at INTEGER,
|
|
14
|
+
CONSTRAINT username_format CHECK (length(username) >= 3 AND length(username) <= 32),
|
|
15
|
+
CONSTRAINT email_format CHECK (email LIKE '%_@__%.__%')
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
-- Index for faster user lookups
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_users_linux_username ON users(linux_username);
|
|
22
|
+
|
|
23
|
+
-- OAuth2 providers table
|
|
24
|
+
CREATE TABLE IF NOT EXISTS oauth2_providers (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
user_id TEXT NOT NULL,
|
|
27
|
+
provider TEXT NOT NULL,
|
|
28
|
+
provider_user_id TEXT NOT NULL,
|
|
29
|
+
provider_email TEXT,
|
|
30
|
+
access_token TEXT,
|
|
31
|
+
refresh_token TEXT,
|
|
32
|
+
token_expires_at INTEGER,
|
|
33
|
+
created_at INTEGER DEFAULT (strftime('%s','now')),
|
|
34
|
+
updated_at INTEGER DEFAULT (strftime('%s','now')),
|
|
35
|
+
UNIQUE(provider, provider_user_id),
|
|
36
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Index for OAuth lookups
|
|
40
|
+
CREATE INDEX IF NOT EXISTS idx_oauth2_user_id ON oauth2_providers(user_id);
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_oauth2_provider_lookup ON oauth2_providers(provider, provider_user_id);
|
|
42
|
+
|
|
43
|
+
-- Sessions table
|
|
44
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
user_id TEXT NOT NULL,
|
|
47
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
48
|
+
ip_address TEXT,
|
|
49
|
+
user_agent TEXT,
|
|
50
|
+
created_at INTEGER DEFAULT (strftime('%s','now')),
|
|
51
|
+
expires_at INTEGER NOT NULL,
|
|
52
|
+
is_revoked INTEGER DEFAULT 0,
|
|
53
|
+
revoked_at INTEGER,
|
|
54
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- Index for session lookups
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_token_hash ON sessions(token_hash);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id);
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_expires_at ON sessions(expires_at);
|
|
61
|
+
|
|
62
|
+
-- Audit log table
|
|
63
|
+
CREATE TABLE IF NOT EXISTS audit_logs (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
user_id TEXT,
|
|
66
|
+
action TEXT NOT NULL,
|
|
67
|
+
resource_type TEXT,
|
|
68
|
+
resource_id TEXT,
|
|
69
|
+
ip_address TEXT,
|
|
70
|
+
user_agent TEXT,
|
|
71
|
+
details TEXT,
|
|
72
|
+
created_at INTEGER DEFAULT (strftime('%s','now')),
|
|
73
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- Index for audit log queries
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_user_id ON audit_logs(user_id);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON audit_logs(action);
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_audit_logs_created_at ON audit_logs(created_at);
|
|
80
|
+
|
|
81
|
+
-- Trigger to update updated_at timestamp for users
|
|
82
|
+
CREATE TRIGGER IF NOT EXISTS update_users_timestamp
|
|
83
|
+
AFTER UPDATE ON users
|
|
84
|
+
FOR EACH ROW
|
|
85
|
+
BEGIN
|
|
86
|
+
UPDATE users SET updated_at = strftime('%s','now') WHERE id = NEW.id;
|
|
87
|
+
END;
|
|
88
|
+
|
|
89
|
+
-- Trigger to update updated_at timestamp for oauth2_providers
|
|
90
|
+
CREATE TRIGGER IF NOT EXISTS update_oauth2_providers_timestamp
|
|
91
|
+
AFTER UPDATE ON oauth2_providers
|
|
92
|
+
FOR EACH ROW
|
|
93
|
+
BEGIN
|
|
94
|
+
UPDATE oauth2_providers SET updated_at = strftime('%s','now') WHERE id = NEW.id;
|
|
95
|
+
END;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import type { User, Session } from "@shared/types.js";
|
|
3
|
+
export type HonoContext = {
|
|
4
|
+
Variables: {
|
|
5
|
+
user?: User;
|
|
6
|
+
session?: Session;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export declare const createApp: () => Hono<HonoContext, import("hono/types").BlankSchema, "/">;
|
|
10
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../src/server/hono/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,MAAM,WAAW,GAAG;IACxB,SAAS,EAAE;QACT,IAAI,CAAC,EAAE,IAAI,CAAC;QACZ,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,SAAS,gEA4BrB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { cors } from "hono/cors";
|
|
3
|
+
import { logger } from "hono/logger";
|
|
4
|
+
export const createApp = () => {
|
|
5
|
+
const app = new Hono();
|
|
6
|
+
app.use("*", logger());
|
|
7
|
+
app.use("*", cors({
|
|
8
|
+
origin: (origin) => {
|
|
9
|
+
if (process.env["NODE_ENV"] === "development") {
|
|
10
|
+
return origin;
|
|
11
|
+
}
|
|
12
|
+
const allowedOrigins = process.env["ALLOWED_ORIGINS"]?.split(",") ?? [];
|
|
13
|
+
return allowedOrigins.includes(origin) ? origin : allowedOrigins[0];
|
|
14
|
+
},
|
|
15
|
+
credentials: true,
|
|
16
|
+
}));
|
|
17
|
+
app.get("/health", (c) => {
|
|
18
|
+
return c.json({
|
|
19
|
+
status: "healthy",
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
uptime: process.uptime(),
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
return app;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/server/hono/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAUrC,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE;IAC5B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAe,CAAC;IAEpC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;IAEvB,GAAG,CAAC,GAAG,CACL,GAAG,EACH,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;YACjB,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,aAAa,EAAE,CAAC;gBAC9C,OAAO,MAAM,CAAC;YAChB,CAAC;YACD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACxE,OAAO,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACtE,CAAC;QACD,WAAW,EAAE,IAAI;KAClB,CAAC,CACH,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;QACvB,OAAO,CAAC,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Hono } from "hono";
|
|
2
|
+
import { Effect, Layer } from "effect";
|
|
3
|
+
import type { HonoContext } from "./app.js";
|
|
4
|
+
import { PasswordService } from "../auth/services/PasswordService.js";
|
|
5
|
+
import { TokenService } from "../auth/services/TokenService.js";
|
|
6
|
+
import { UserRepository } from "../auth/services/UserRepository.js";
|
|
7
|
+
import { SessionRepository } from "../auth/services/SessionRepository.js";
|
|
8
|
+
import { AuditLogService } from "../auth/services/AuditLogService.js";
|
|
9
|
+
import { AuthService } from "../auth/services/AuthService.js";
|
|
10
|
+
export declare const AppLayer: Layer.Layer<PasswordService | TokenService | UserRepository | SessionRepository | AuditLogService | AuthService, import("../../shared/types.js").AuthError, PasswordService | TokenService | import("../database/db.js").DatabaseService | UserRepository | SessionRepository | AuditLogService>;
|
|
11
|
+
export declare const setupRoutes: (app: Hono<HonoContext>) => Effect.Effect<void, never>;
|
|
12
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/server/hono/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAK9D,eAAO,MAAM,QAAQ,kSAOpB,CAAC;AAGF,eAAO,MAAM,WAAW,GAAI,KAAK,IAAI,CAAC,WAAW,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CA8B1E,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Effect, Layer } from "effect";
|
|
2
|
+
import { PasswordService } from "../auth/services/PasswordService.js";
|
|
3
|
+
import { TokenService } from "../auth/services/TokenService.js";
|
|
4
|
+
import { UserRepository } from "../auth/services/UserRepository.js";
|
|
5
|
+
import { SessionRepository } from "../auth/services/SessionRepository.js";
|
|
6
|
+
import { AuditLogService } from "../auth/services/AuditLogService.js";
|
|
7
|
+
import { AuthService } from "../auth/services/AuthService.js";
|
|
8
|
+
import authRouter from "../auth/routes/authRoutes.js";
|
|
9
|
+
import authMiddleware from "../auth/middleware/authMiddleware.js";
|
|
10
|
+
// Create the application service layer that requires DatabaseService
|
|
11
|
+
export const AppLayer = Layer.mergeAll(PasswordService.Live, TokenService.Live, AuditLogService.Live).pipe(Layer.provideMerge(Layer.mergeAll(UserRepository.Live, SessionRepository.Live)), Layer.provideMerge(AuthService.Live));
|
|
12
|
+
// Setup routes with Effect-TS dependencies
|
|
13
|
+
export const setupRoutes = (app) => Effect.gen(function* () {
|
|
14
|
+
// Mount auth routes
|
|
15
|
+
app.route("/api/auth", authRouter);
|
|
16
|
+
// Example protected route
|
|
17
|
+
app.get("/api/protected", authMiddleware, (c) => {
|
|
18
|
+
const user = c.get("user");
|
|
19
|
+
const session = c.get("session");
|
|
20
|
+
return c.json({
|
|
21
|
+
message: "This is a protected route",
|
|
22
|
+
user: {
|
|
23
|
+
id: user?.id,
|
|
24
|
+
username: user?.username,
|
|
25
|
+
email: user?.email,
|
|
26
|
+
},
|
|
27
|
+
session: {
|
|
28
|
+
id: session?.id,
|
|
29
|
+
expiresAt: session?.expiresAt,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
console.log("✅ Routes configured successfully");
|
|
34
|
+
console.log(" 📍 POST /api/auth/register - User registration");
|
|
35
|
+
console.log(" 📍 POST /api/auth/login - User login");
|
|
36
|
+
console.log(" 📍 POST /api/auth/logout - User logout (protected)");
|
|
37
|
+
console.log(" 📍 GET /api/auth/me - Current user info (protected)");
|
|
38
|
+
console.log(" 📍 GET /api/protected - Example protected route");
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/server/hono/routes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,UAAU,MAAM,8BAA8B,CAAC;AACtD,OAAO,cAAc,MAAM,sCAAsC,CAAC;AAElE,qEAAqE;AACrE,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CACpC,eAAe,CAAC,IAAI,EACpB,YAAY,CAAC,IAAI,EACjB,eAAe,CAAC,IAAI,CACrB,CAAC,IAAI,CACJ,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAC/E,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,CACrC,CAAC;AAEF,2CAA2C;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAsB,EAA8B,EAAE,CAChF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,oBAAoB;IACpB,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAEnC,0BAA0B;IAC1B,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE;QAC9C,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEjC,OAAO,CAAC,CAAC,IAAI,CAAC;YACZ,OAAO,EAAE,2BAA2B;YACpC,IAAI,EAAE;gBACJ,EAAE,EAAE,IAAI,EAAE,EAAE;gBACZ,QAAQ,EAAE,IAAI,EAAE,QAAQ;gBACxB,KAAK,EAAE,IAAI,EAAE,KAAK;aACnB;YACD,OAAO,EAAE;gBACP,EAAE,EAAE,OAAO,EAAE,EAAE;gBACf,SAAS,EAAE,OAAO,EAAE,SAAS;aAC9B;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/server/main.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { serve } from "@hono/node-server";
|
|
2
|
+
import { Effect, ManagedRuntime } from "effect";
|
|
3
|
+
import { NodeContext } from "@effect/platform-node";
|
|
4
|
+
import { createApp } from "./hono/app.js";
|
|
5
|
+
import { createAuthRoutes } from "./auth/routes/authRoutes.js";
|
|
6
|
+
import { createAuthMiddleware } from "./auth/middleware/authMiddleware.js";
|
|
7
|
+
import { createAppLayer } from "./auth/layers.js";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
const getDefaultDbPath = () => {
|
|
11
|
+
const sqliteDbPath = process.env["SQLITE_DB_PATH"];
|
|
12
|
+
if (sqliteDbPath) {
|
|
13
|
+
return sqliteDbPath;
|
|
14
|
+
}
|
|
15
|
+
if (process.env["SINGLE_USER_MODE"] === "true") {
|
|
16
|
+
const home = homedir();
|
|
17
|
+
return path.join(home, ".myaidev-web", "users.db");
|
|
18
|
+
}
|
|
19
|
+
return path.join(process.cwd(), "data", "users.db");
|
|
20
|
+
};
|
|
21
|
+
// Create the application layer with auth services
|
|
22
|
+
const AppLayer = createAppLayer({
|
|
23
|
+
path: getDefaultDbPath(),
|
|
24
|
+
timeout: 5000,
|
|
25
|
+
verbose: false, // Disable verbose mode to prevent schema logging on every request
|
|
26
|
+
});
|
|
27
|
+
// Build the managed runtime once at startup (memoization with automatic scope management)
|
|
28
|
+
const AppRuntime = ManagedRuntime.make(AppLayer);
|
|
29
|
+
// Create middleware and routes with the memoized runtime
|
|
30
|
+
const authMiddleware = createAuthMiddleware(AppRuntime);
|
|
31
|
+
const authRouter = createAuthRoutes(AppRuntime, authMiddleware);
|
|
32
|
+
const program = Effect.gen(function* () {
|
|
33
|
+
const port = Number.parseInt(process.env["PORT"] ?? "3400", 10);
|
|
34
|
+
const dbPath = getDefaultDbPath();
|
|
35
|
+
console.log(`🔧 Initializing MyAIDev Method Web Server`);
|
|
36
|
+
console.log(`📂 Database path: ${dbPath}`);
|
|
37
|
+
console.log(`🌐 Server port: ${port}`);
|
|
38
|
+
console.log(`✅ Application layer initialized successfully`);
|
|
39
|
+
const app = createApp();
|
|
40
|
+
console.log(`🚀 Starting server on port ${port}...`);
|
|
41
|
+
// Mount authentication routes (already created with AppLayer)
|
|
42
|
+
app.route("/api/auth", authRouter);
|
|
43
|
+
// Example protected route
|
|
44
|
+
app.get("/api/protected", authMiddleware, (c) => {
|
|
45
|
+
const user = c.get("user");
|
|
46
|
+
const session = c.get("session");
|
|
47
|
+
return c.json({
|
|
48
|
+
message: "This is a protected route",
|
|
49
|
+
user: {
|
|
50
|
+
id: user?.id,
|
|
51
|
+
username: user?.username,
|
|
52
|
+
email: user?.email,
|
|
53
|
+
},
|
|
54
|
+
session: {
|
|
55
|
+
id: session?.id,
|
|
56
|
+
expiresAt: session?.expiresAt,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
console.log("✅ Routes configured successfully");
|
|
61
|
+
console.log(" 📍 POST /api/auth/register - User registration");
|
|
62
|
+
console.log(" 📍 POST /api/auth/login - User login");
|
|
63
|
+
console.log(" 📍 POST /api/auth/logout - User logout (protected)");
|
|
64
|
+
console.log(" 📍 GET /api/auth/me - Current user info (protected)");
|
|
65
|
+
console.log(" 📍 GET /api/protected - Example protected route");
|
|
66
|
+
const server = serve({
|
|
67
|
+
fetch: app.fetch,
|
|
68
|
+
port,
|
|
69
|
+
});
|
|
70
|
+
console.log(`✅ Server running at http://localhost:${port}`);
|
|
71
|
+
console.log(`📊 Health check: http://localhost:${port}/health`);
|
|
72
|
+
yield* Effect.async(() => {
|
|
73
|
+
process.on("SIGTERM", () => {
|
|
74
|
+
console.log("\n🛑 SIGTERM received, shutting down gracefully...");
|
|
75
|
+
server.close(() => {
|
|
76
|
+
console.log("✅ Server closed");
|
|
77
|
+
process.exit(0);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
process.on("SIGINT", () => {
|
|
81
|
+
console.log("\n🛑 SIGINT received, shutting down gracefully...");
|
|
82
|
+
server.close(() => {
|
|
83
|
+
console.log("✅ Server closed");
|
|
84
|
+
process.exit(0);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
// Program only needs Node context
|
|
90
|
+
Effect.runPromise(Effect.provide(program, NodeContext.layer)).catch((error) => {
|
|
91
|
+
console.error("❌ Fatal error:", error);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/server/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Effect, Context, Layer } from "effect";
|
|
2
|
+
/**
|
|
3
|
+
* Directory Management Service
|
|
4
|
+
*
|
|
5
|
+
* Handles creation and management of user home directories,
|
|
6
|
+
* Claude Code configurations, and workspace setup for isolated
|
|
7
|
+
* multi-user environments.
|
|
8
|
+
*
|
|
9
|
+
* Directory Structure:
|
|
10
|
+
* /home/{username}/
|
|
11
|
+
* ├── .claude/ # Claude Code configuration
|
|
12
|
+
* │ ├── config.json # User-specific Claude settings
|
|
13
|
+
* │ ├── sessions/ # Session storage
|
|
14
|
+
* │ └── cache/ # Cache directory
|
|
15
|
+
* ├── workspace/ # User's workspace directory
|
|
16
|
+
* └── .bashrc # Shell configuration
|
|
17
|
+
*/
|
|
18
|
+
export interface DirectorySetupOptions {
|
|
19
|
+
username: string;
|
|
20
|
+
homeDir: string;
|
|
21
|
+
uid: number;
|
|
22
|
+
gid: number;
|
|
23
|
+
claudeConfig?: ClaudeConfig;
|
|
24
|
+
}
|
|
25
|
+
export interface ClaudeConfig {
|
|
26
|
+
apiKey?: string;
|
|
27
|
+
model?: string;
|
|
28
|
+
maxTokens?: number;
|
|
29
|
+
temperature?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface DirectoryError {
|
|
32
|
+
readonly _tag: "DirectoryError";
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly cause?: unknown;
|
|
35
|
+
}
|
|
36
|
+
declare const DirectoryService_base: Context.TagClass<DirectoryService, "DirectoryService", {
|
|
37
|
+
/**
|
|
38
|
+
* Set up complete home directory structure for a user
|
|
39
|
+
*/
|
|
40
|
+
readonly setupHomeDirectory: (options: DirectorySetupOptions) => Effect.Effect<void, DirectoryError>;
|
|
41
|
+
/**
|
|
42
|
+
* Create Claude Code configuration directory
|
|
43
|
+
*/
|
|
44
|
+
readonly createClaudeConfig: (homeDir: string, config: ClaudeConfig, uid: number, gid: number) => Effect.Effect<void, DirectoryError>;
|
|
45
|
+
/**
|
|
46
|
+
* Create user workspace directory
|
|
47
|
+
*/
|
|
48
|
+
readonly createWorkspace: (homeDir: string, uid: number, gid: number) => Effect.Effect<void, DirectoryError>;
|
|
49
|
+
/**
|
|
50
|
+
* Set proper ownership and permissions
|
|
51
|
+
*/
|
|
52
|
+
readonly setOwnership: (dirPath: string, uid: number, gid: number, recursive?: boolean) => Effect.Effect<void, DirectoryError>;
|
|
53
|
+
/**
|
|
54
|
+
* Clean up user directories
|
|
55
|
+
*/
|
|
56
|
+
readonly cleanupDirectories: (homeDir: string) => Effect.Effect<void, DirectoryError>;
|
|
57
|
+
}>;
|
|
58
|
+
export declare class DirectoryService extends DirectoryService_base {
|
|
59
|
+
static Live: Layer.Layer<DirectoryService, never, never>;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=DirectoryService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectoryService.d.ts","sourceRoot":"","sources":["../../../src/server/user-management/DirectoryService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAKhD;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;;IAWG;;OAEG;iCAC0B,CAC3B,OAAO,EAAE,qBAAqB,KAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;IAExC;;OAEG;iCAC0B,CAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;IAExC;;OAEG;8BACuB,CACxB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;IAExC;;OAEG;2BACoB,CACrB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,OAAO,KAChB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;IAExC;;OAEG;iCAC0B,CAC3B,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;;AA5C5C,qBAAa,gBAAiB,SAAQ,qBA8CnC;IACD,MAAM,CAAC,IAAI,8CA0PR;CACJ"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { Effect, Context, Layer } from "effect";
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
const DirectoryError = (message, cause) => ({
|
|
6
|
+
_tag: "DirectoryError",
|
|
7
|
+
message,
|
|
8
|
+
cause,
|
|
9
|
+
});
|
|
10
|
+
export class DirectoryService extends Context.Tag("DirectoryService")() {
|
|
11
|
+
static Live = Layer.succeed(this, {
|
|
12
|
+
setupHomeDirectory: (options) => Effect.gen(function* () {
|
|
13
|
+
const { username, homeDir, uid, gid, claudeConfig } = options;
|
|
14
|
+
// Ensure home directory exists (should be created by useradd)
|
|
15
|
+
yield* Effect.tryPromise({
|
|
16
|
+
try: async () => {
|
|
17
|
+
await fs.access(homeDir);
|
|
18
|
+
},
|
|
19
|
+
catch: (error) => DirectoryError(`Home directory ${homeDir} does not exist. Create user first.`, error),
|
|
20
|
+
});
|
|
21
|
+
// Create .claude directory
|
|
22
|
+
const claudeDir = path.join(homeDir, ".claude");
|
|
23
|
+
yield* Effect.tryPromise({
|
|
24
|
+
try: async () => {
|
|
25
|
+
await fs.mkdir(claudeDir, { recursive: true, mode: 0o755 });
|
|
26
|
+
},
|
|
27
|
+
catch: (error) => DirectoryError(`Failed to create .claude directory`, error),
|
|
28
|
+
});
|
|
29
|
+
// Create subdirectories
|
|
30
|
+
const subdirs = ["sessions", "cache", "workspace"];
|
|
31
|
+
for (const subdir of subdirs) {
|
|
32
|
+
const subdirPath = subdir === "workspace"
|
|
33
|
+
? path.join(homeDir, subdir)
|
|
34
|
+
: path.join(claudeDir, subdir);
|
|
35
|
+
yield* Effect.tryPromise({
|
|
36
|
+
try: async () => {
|
|
37
|
+
await fs.mkdir(subdirPath, { recursive: true, mode: 0o755 });
|
|
38
|
+
},
|
|
39
|
+
catch: (error) => DirectoryError(`Failed to create ${subdir} directory`, error),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// Create Claude config file
|
|
43
|
+
if (claudeConfig) {
|
|
44
|
+
const configPath = path.join(claudeDir, "config.json");
|
|
45
|
+
const configContent = JSON.stringify({
|
|
46
|
+
apiKey: claudeConfig.apiKey || "",
|
|
47
|
+
model: claudeConfig.model || "claude-sonnet-4-20250514",
|
|
48
|
+
maxTokens: claudeConfig.maxTokens || 8192,
|
|
49
|
+
temperature: claudeConfig.temperature || 1.0,
|
|
50
|
+
username,
|
|
51
|
+
createdAt: new Date().toISOString(),
|
|
52
|
+
}, null, 2);
|
|
53
|
+
yield* Effect.tryPromise({
|
|
54
|
+
try: async () => {
|
|
55
|
+
await fs.writeFile(configPath, configContent, {
|
|
56
|
+
mode: 0o600,
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
catch: (error) => DirectoryError("Failed to create Claude config file", error),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// Create .bashrc with helpful aliases
|
|
63
|
+
const bashrcPath = path.join(homeDir, ".bashrc");
|
|
64
|
+
const bashrcContent = `# MyAIDev Method User Environment
|
|
65
|
+
# Generated on ${new Date().toISOString()}
|
|
66
|
+
|
|
67
|
+
# Helpful aliases
|
|
68
|
+
alias ll='ls -alh'
|
|
69
|
+
alias workspace='cd ~/workspace'
|
|
70
|
+
alias claude='cd ~/.claude'
|
|
71
|
+
|
|
72
|
+
# Environment
|
|
73
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
74
|
+
export CLAUDE_CONFIG_DIR="$HOME/.claude"
|
|
75
|
+
|
|
76
|
+
# Workspace directory
|
|
77
|
+
export WORKSPACE="$HOME/workspace"
|
|
78
|
+
|
|
79
|
+
# Welcome message
|
|
80
|
+
echo "Welcome to MyAIDev Method, ${username}!"
|
|
81
|
+
echo "Your workspace is in: ~/workspace"
|
|
82
|
+
`;
|
|
83
|
+
yield* Effect.tryPromise({
|
|
84
|
+
try: async () => {
|
|
85
|
+
await fs.writeFile(bashrcPath, bashrcContent, { mode: 0o644 });
|
|
86
|
+
},
|
|
87
|
+
catch: (error) => DirectoryError("Failed to create .bashrc file", error),
|
|
88
|
+
});
|
|
89
|
+
// Set ownership of all created files/directories
|
|
90
|
+
yield* Effect.tryPromise({
|
|
91
|
+
try: async () => {
|
|
92
|
+
execSync(`sudo chown -R ${uid}:${gid} ${homeDir}`, {
|
|
93
|
+
stdio: "pipe",
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
catch: (error) => DirectoryError(`Failed to set ownership for ${homeDir}`, error),
|
|
97
|
+
});
|
|
98
|
+
// Set proper permissions
|
|
99
|
+
yield* Effect.tryPromise({
|
|
100
|
+
try: async () => {
|
|
101
|
+
execSync(`sudo chmod 755 ${homeDir}`, { stdio: "pipe" });
|
|
102
|
+
execSync(`sudo chmod 700 ${claudeDir}`, { stdio: "pipe" });
|
|
103
|
+
execSync(`sudo chmod 755 ${path.join(homeDir, "workspace")}`, {
|
|
104
|
+
stdio: "pipe",
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
catch: (error) => DirectoryError("Failed to set directory permissions", error),
|
|
108
|
+
});
|
|
109
|
+
}),
|
|
110
|
+
createClaudeConfig: (homeDir, config, uid, gid) => Effect.gen(function* () {
|
|
111
|
+
const claudeDir = path.join(homeDir, ".claude");
|
|
112
|
+
const configPath = path.join(claudeDir, "config.json");
|
|
113
|
+
// Ensure .claude directory exists
|
|
114
|
+
yield* Effect.tryPromise({
|
|
115
|
+
try: async () => {
|
|
116
|
+
await fs.mkdir(claudeDir, { recursive: true, mode: 0o700 });
|
|
117
|
+
},
|
|
118
|
+
catch: (error) => DirectoryError("Failed to create .claude directory", error),
|
|
119
|
+
});
|
|
120
|
+
// Write config file
|
|
121
|
+
const configContent = JSON.stringify(config, null, 2);
|
|
122
|
+
yield* Effect.tryPromise({
|
|
123
|
+
try: async () => {
|
|
124
|
+
await fs.writeFile(configPath, configContent, { mode: 0o600 });
|
|
125
|
+
},
|
|
126
|
+
catch: (error) => DirectoryError("Failed to write Claude config", error),
|
|
127
|
+
});
|
|
128
|
+
// Set ownership
|
|
129
|
+
yield* Effect.tryPromise({
|
|
130
|
+
try: async () => {
|
|
131
|
+
execSync(`sudo chown -R ${uid}:${gid} ${claudeDir}`, {
|
|
132
|
+
stdio: "pipe",
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
catch: (error) => DirectoryError("Failed to set config ownership", error),
|
|
136
|
+
});
|
|
137
|
+
}),
|
|
138
|
+
createWorkspace: (homeDir, uid, gid) => Effect.gen(function* () {
|
|
139
|
+
const workspaceDir = path.join(homeDir, "workspace");
|
|
140
|
+
// Create workspace directory
|
|
141
|
+
yield* Effect.tryPromise({
|
|
142
|
+
try: async () => {
|
|
143
|
+
await fs.mkdir(workspaceDir, { recursive: true, mode: 0o755 });
|
|
144
|
+
},
|
|
145
|
+
catch: (error) => DirectoryError("Failed to create workspace directory", error),
|
|
146
|
+
});
|
|
147
|
+
// Create a README file
|
|
148
|
+
const readmePath = path.join(workspaceDir, "README.md");
|
|
149
|
+
const readmeContent = `# Welcome to Your MyAIDev Method Workspace
|
|
150
|
+
|
|
151
|
+
This is your personal workspace for AI-assisted development with Claude Code.
|
|
152
|
+
|
|
153
|
+
## Directory Structure
|
|
154
|
+
|
|
155
|
+
- Use this workspace to create and manage your projects
|
|
156
|
+
- Claude Code will have access to files in this directory
|
|
157
|
+
- Your work is isolated from other users
|
|
158
|
+
|
|
159
|
+
## Getting Started
|
|
160
|
+
|
|
161
|
+
1. Create a new project directory
|
|
162
|
+
2. Initialize your project (git init, npm init, etc.)
|
|
163
|
+
3. Start working with Claude Code assistance
|
|
164
|
+
|
|
165
|
+
Happy coding!
|
|
166
|
+
`;
|
|
167
|
+
yield* Effect.tryPromise({
|
|
168
|
+
try: async () => {
|
|
169
|
+
await fs.writeFile(readmePath, readmeContent, { mode: 0o644 });
|
|
170
|
+
},
|
|
171
|
+
catch: (error) => DirectoryError("Failed to create workspace README", error),
|
|
172
|
+
});
|
|
173
|
+
// Set ownership
|
|
174
|
+
yield* Effect.tryPromise({
|
|
175
|
+
try: async () => {
|
|
176
|
+
execSync(`sudo chown -R ${uid}:${gid} ${workspaceDir}`, {
|
|
177
|
+
stdio: "pipe",
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
catch: (error) => DirectoryError("Failed to set workspace ownership", error),
|
|
181
|
+
});
|
|
182
|
+
}),
|
|
183
|
+
setOwnership: (dirPath, uid, gid, recursive = false) => Effect.tryPromise({
|
|
184
|
+
try: async () => {
|
|
185
|
+
const recursiveFlag = recursive ? "-R" : "";
|
|
186
|
+
execSync(`sudo chown ${recursiveFlag} ${uid}:${gid} ${dirPath}`, {
|
|
187
|
+
stdio: "pipe",
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
catch: (error) => DirectoryError(`Failed to set ownership for ${dirPath}`, error),
|
|
191
|
+
}),
|
|
192
|
+
cleanupDirectories: (homeDir) => Effect.tryPromise({
|
|
193
|
+
try: async () => {
|
|
194
|
+
// Remove home directory and all contents
|
|
195
|
+
execSync(`sudo rm -rf ${homeDir}`, { stdio: "pipe" });
|
|
196
|
+
},
|
|
197
|
+
catch: (error) => DirectoryError(`Failed to cleanup directories for ${homeDir}`, error),
|
|
198
|
+
}),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=DirectoryService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DirectoryService.js","sourceRoot":"","sources":["../../../src/server/user-management/DirectoryService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAwC7B,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,KAAe,EAAkB,EAAE,CAAC,CAAC;IAC5E,IAAI,EAAE,gBAAgB;IACtB,OAAO;IACP,KAAK;CACN,CAAC,CAAC;AAEH,MAAM,OAAO,gBAAiB,SAAQ,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EA8ClE;IACD,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE;QAChC,kBAAkB,EAAE,CAAC,OAA8B,EAAE,EAAE,CACrD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;YAE9D,8DAA8D;YAC9D,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC3B,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CACZ,kBAAkB,OAAO,qCAAqC,EAC9D,KAAK,CACN;aACJ,CAAC,CAAC;YAEH,2BAA2B;YAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAChD,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC9D,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,oCAAoC,EAAE,KAAK,CAAC;aAC9D,CAAC,CAAC;YAEH,wBAAwB;YACxB,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;YACnD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,UAAU,GACd,MAAM,KAAK,WAAW;oBACpB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC;oBAC5B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBAEnC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;oBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;wBACd,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC/D,CAAC;oBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,oBAAoB,MAAM,YAAY,EAAE,KAAK,CAAC;iBAChE,CAAC,CAAC;YACL,CAAC;YAED,4BAA4B;YAC5B,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;gBACvD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAClC;oBACE,MAAM,EAAE,YAAY,CAAC,MAAM,IAAI,EAAE;oBACjC,KAAK,EAAE,YAAY,CAAC,KAAK,IAAI,0BAA0B;oBACvD,SAAS,EAAE,YAAY,CAAC,SAAS,IAAI,IAAI;oBACzC,WAAW,EAAE,YAAY,CAAC,WAAW,IAAI,GAAG;oBAC5C,QAAQ;oBACR,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,EACD,IAAI,EACJ,CAAC,CACF,CAAC;gBAEF,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;oBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;wBACd,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE;4BAC5C,IAAI,EAAE,KAAK;yBACZ,CAAC,CAAC;oBACL,CAAC;oBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,qCAAqC,EAAE,KAAK,CAAC;iBAC/D,CAAC,CAAC;YACL,CAAC;YAED,sCAAsC;YACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACjD,MAAM,aAAa,GAAG;iBACb,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;;;;;;;;;;;;;;;mCAeN,QAAQ;;CAE1C,CAAC;YAEM,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjE,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,+BAA+B,EAAE,KAAK,CAAC;aACzD,CAAC,CAAC;YAEH,iDAAiD;YACjD,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,QAAQ,CAAC,iBAAiB,GAAG,IAAI,GAAG,IAAI,OAAO,EAAE,EAAE;wBACjD,KAAK,EAAE,MAAM;qBACd,CAAC,CAAC;gBACL,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CACZ,+BAA+B,OAAO,EAAE,EACxC,KAAK,CACN;aACJ,CAAC,CAAC;YAEH,yBAAyB;YACzB,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,QAAQ,CAAC,kBAAkB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;oBACzD,QAAQ,CAAC,kBAAkB,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC3D,QAAQ,CAAC,kBAAkB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE;wBAC5D,KAAK,EAAE,MAAM;qBACd,CAAC,CAAC;gBACL,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,qCAAqC,EAAE,KAAK,CAAC;aAC/D,CAAC,CAAC;QACL,CAAC,CAAC;QAEJ,kBAAkB,EAAE,CAClB,OAAe,EACf,MAAoB,EACpB,GAAW,EACX,GAAW,EACX,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;YAEvD,kCAAkC;YAClC,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC9D,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,oCAAoC,EAAE,KAAK,CAAC;aAC9D,CAAC,CAAC;YAEH,oBAAoB;YACpB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACtD,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjE,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,+BAA+B,EAAE,KAAK,CAAC;aACzD,CAAC,CAAC;YAEH,gBAAgB;YAChB,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,QAAQ,CAAC,iBAAiB,GAAG,IAAI,GAAG,IAAI,SAAS,EAAE,EAAE;wBACnD,KAAK,EAAE,MAAM;qBACd,CAAC,CAAC;gBACL,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,gCAAgC,EAAE,KAAK,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC,CAAC;QAEJ,eAAe,EAAE,CAAC,OAAe,EAAE,GAAW,EAAE,GAAW,EAAE,EAAE,CAC7D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAErD,6BAA6B;YAC7B,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjE,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,sCAAsC,EAAE,KAAK,CAAC;aAChE,CAAC,CAAC;YAEH,uBAAuB;YACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;YACxD,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;CAiB7B,CAAC;YAEM,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjE,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,mCAAmC,EAAE,KAAK,CAAC;aAC7D,CAAC,CAAC;YAEH,gBAAgB;YAChB,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;gBACvB,GAAG,EAAE,KAAK,IAAI,EAAE;oBACd,QAAQ,CAAC,iBAAiB,GAAG,IAAI,GAAG,IAAI,YAAY,EAAE,EAAE;wBACtD,KAAK,EAAE,MAAM;qBACd,CAAC,CAAC;gBACL,CAAC;gBACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,mCAAmC,EAAE,KAAK,CAAC;aAC7D,CAAC,CAAC;QACL,CAAC,CAAC;QAEJ,YAAY,EAAE,CACZ,OAAe,EACf,GAAW,EACX,GAAW,EACX,YAAqB,KAAK,EAC1B,EAAE,CACF,MAAM,CAAC,UAAU,CAAC;YAChB,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,cAAc,aAAa,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,EAAE,EAAE;oBAC/D,KAAK,EAAE,MAAM;iBACd,CAAC,CAAC;YACL,CAAC;YACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,+BAA+B,OAAO,EAAE,EAAE,KAAK,CAAC;SAClE,CAAC;QAEJ,kBAAkB,EAAE,CAAC,OAAe,EAAE,EAAE,CACtC,MAAM,CAAC,UAAU,CAAC;YAChB,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,yCAAyC;gBACzC,QAAQ,CAAC,eAAe,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,cAAc,CAAC,qCAAqC,OAAO,EAAE,EAAE,KAAK,CAAC;SACxE,CAAC;KACL,CAAC,CAAC"}
|