@ultrst-armada/kloks 1.7.1 → 1.9.0
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/.krusbl-release-attestation.json +3 -3
- package/package.json +1 -1
- package/packages/backend/dist/{BaseStorageAdapter-6x_BQiB3.d.ts → BaseStorageAdapter-EUCSvJse.d.ts} +1 -0
- package/packages/backend/dist/auth/index.d.ts +51 -13
- package/packages/backend/dist/auth/index.js +6 -2
- package/packages/backend/dist/{chunk-6W7OAGNV.js → chunk-BTMIK44G.js} +84 -1
- package/packages/backend/dist/chunk-KKRWZDMN.js +237 -0
- package/packages/backend/dist/{chunk-JUPWFW7V.js → chunk-RBQ4CW3T.js} +4 -2
- package/packages/backend/dist/{chunk-R45CEV46.js → chunk-SHZAQTIT.js} +4 -234
- package/packages/backend/dist/{chunk-7ZT2ZPPH.js → chunk-UMEO6XS4.js} +5 -5
- package/packages/backend/dist/{chunk-F6IDQLC2.js → chunk-VKSGYMAH.js} +1 -1
- package/packages/backend/dist/{chunk-MPYASJ5A.js → chunk-W6JNJD3Q.js} +1 -1
- package/packages/backend/dist/chunk-WTBAG4AV.js +207 -0
- package/packages/backend/dist/index.d.ts +43 -4
- package/packages/backend/dist/index.js +163 -13
- package/packages/backend/dist/krnl-services.js +5 -4
- package/packages/backend/dist/services/index.js +3 -2
- package/packages/backend/dist/storage/index.d.ts +2 -2
- package/packages/backend/dist/storage/index.js +9 -7
- package/packages/backend/dist/workspace/index.d.ts +1 -1
- package/packages/backend/dist/workspace/index.js +2 -1
- package/packages/contracts/dist/index.d.ts +106 -1
- package/packages/contracts/dist/index.js +61 -0
- package/packages/services/dist/index.d.ts +36 -2
- package/packages/services/dist/index.js +251 -0
- package/packages/state-graph/dist/index.js +15 -15
- package/packages/backend/dist/chunk-ZDH4XI7W.js +0 -140
|
@@ -1651,6 +1651,251 @@ var StorageService = class {
|
|
|
1651
1651
|
};
|
|
1652
1652
|
var storageService = new StorageService();
|
|
1653
1653
|
|
|
1654
|
+
// src/client-services/monacoIdeService.ts
|
|
1655
|
+
var activeMonacoService;
|
|
1656
|
+
var MonacoIdeServiceDefinition = createServiceDefinition({
|
|
1657
|
+
id: "kloks.service.monacoIde",
|
|
1658
|
+
name: "MonacoIdeService",
|
|
1659
|
+
version: "1.0.0",
|
|
1660
|
+
state: { initial: { sessions: {} } },
|
|
1661
|
+
operations: {
|
|
1662
|
+
createSession: {
|
|
1663
|
+
id: "MonacoIdeService.createSession",
|
|
1664
|
+
name: "createSession",
|
|
1665
|
+
handler: async (input, ctx) => {
|
|
1666
|
+
const sessionId = input.sessionId || `monaco-${Date.now().toString(36)}`;
|
|
1667
|
+
const now = Date.now();
|
|
1668
|
+
const session = {
|
|
1669
|
+
sessionId,
|
|
1670
|
+
document: { uri: input.uri, language: input.language, value: input.value, version: 1, diagnostics: [] },
|
|
1671
|
+
options: input.options || {},
|
|
1672
|
+
createdAt: now,
|
|
1673
|
+
updatedAt: now
|
|
1674
|
+
};
|
|
1675
|
+
activeMonacoService.setState({ sessions: { ...activeMonacoService.getState().sessions, [sessionId]: session } });
|
|
1676
|
+
return session;
|
|
1677
|
+
}
|
|
1678
|
+
},
|
|
1679
|
+
updateDocument: {
|
|
1680
|
+
id: "MonacoIdeService.updateDocument",
|
|
1681
|
+
name: "updateDocument",
|
|
1682
|
+
handler: async (input, ctx) => {
|
|
1683
|
+
const current = activeMonacoService.getState().sessions[input.sessionId];
|
|
1684
|
+
if (!current) throw new Error(`Unknown Monaco session: ${input.sessionId}`);
|
|
1685
|
+
const document = {
|
|
1686
|
+
...current.document,
|
|
1687
|
+
value: input.value,
|
|
1688
|
+
language: input.language || current.document.language,
|
|
1689
|
+
version: current.document.version + 1
|
|
1690
|
+
};
|
|
1691
|
+
const session = { ...current, document, updatedAt: Date.now() };
|
|
1692
|
+
activeMonacoService.setState({ sessions: { ...activeMonacoService.getState().sessions, [session.sessionId]: session } });
|
|
1693
|
+
return session;
|
|
1694
|
+
}
|
|
1695
|
+
},
|
|
1696
|
+
setDiagnostics: {
|
|
1697
|
+
id: "MonacoIdeService.setDiagnostics",
|
|
1698
|
+
name: "setDiagnostics",
|
|
1699
|
+
handler: async (input, ctx) => {
|
|
1700
|
+
const current = activeMonacoService.getState().sessions[input.sessionId];
|
|
1701
|
+
if (!current) throw new Error(`Unknown Monaco session: ${input.sessionId}`);
|
|
1702
|
+
const session = {
|
|
1703
|
+
...current,
|
|
1704
|
+
document: { ...current.document, diagnostics: input.diagnostics },
|
|
1705
|
+
updatedAt: Date.now()
|
|
1706
|
+
};
|
|
1707
|
+
activeMonacoService.setState({ sessions: { ...activeMonacoService.getState().sessions, [session.sessionId]: session } });
|
|
1708
|
+
return session;
|
|
1709
|
+
}
|
|
1710
|
+
},
|
|
1711
|
+
setOptions: {
|
|
1712
|
+
id: "MonacoIdeService.setOptions",
|
|
1713
|
+
name: "setOptions",
|
|
1714
|
+
handler: async (input, ctx) => {
|
|
1715
|
+
const current = activeMonacoService.getState().sessions[input.sessionId];
|
|
1716
|
+
if (!current) throw new Error(`Unknown Monaco session: ${input.sessionId}`);
|
|
1717
|
+
const session = { ...current, options: { ...current.options, ...input.options }, updatedAt: Date.now() };
|
|
1718
|
+
activeMonacoService.setState({ sessions: { ...activeMonacoService.getState().sessions, [session.sessionId]: session } });
|
|
1719
|
+
return session;
|
|
1720
|
+
}
|
|
1721
|
+
},
|
|
1722
|
+
getSession: {
|
|
1723
|
+
id: "MonacoIdeService.getSession",
|
|
1724
|
+
name: "getSession",
|
|
1725
|
+
handler: async (input, ctx) => activeMonacoService.getState().sessions[input.sessionId] || null
|
|
1726
|
+
},
|
|
1727
|
+
disposeSession: {
|
|
1728
|
+
id: "MonacoIdeService.disposeSession",
|
|
1729
|
+
name: "disposeSession",
|
|
1730
|
+
handler: async (input, ctx) => {
|
|
1731
|
+
const sessions = { ...activeMonacoService.getState().sessions };
|
|
1732
|
+
delete sessions[input.sessionId];
|
|
1733
|
+
activeMonacoService.setState({ sessions });
|
|
1734
|
+
return { disposed: true, sessionId: input.sessionId };
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
function createMonacoIdeService() {
|
|
1740
|
+
activeMonacoService = createService(MonacoIdeServiceDefinition);
|
|
1741
|
+
return activeMonacoService;
|
|
1742
|
+
}
|
|
1743
|
+
var defaultMonacoIdeService = createMonacoIdeService();
|
|
1744
|
+
var MonacoIdeServiceFacade = {
|
|
1745
|
+
id: MonacoIdeServiceDefinition.id,
|
|
1746
|
+
name: MonacoIdeServiceDefinition.name,
|
|
1747
|
+
version: MonacoIdeServiceDefinition.version,
|
|
1748
|
+
runtime: "client",
|
|
1749
|
+
deployment: "local",
|
|
1750
|
+
definition: MonacoIdeServiceDefinition,
|
|
1751
|
+
service: defaultMonacoIdeService,
|
|
1752
|
+
createInstance: createMonacoIdeService,
|
|
1753
|
+
execute: async (operation, input) => {
|
|
1754
|
+
await defaultMonacoIdeService.start();
|
|
1755
|
+
return defaultMonacoIdeService.call(operation, input);
|
|
1756
|
+
}
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
// src/client-services/uiAuthoringService.ts
|
|
1760
|
+
import { buildServiceUISchema, suggestUIComponent } from "@ultrst-armada/kloks/contracts";
|
|
1761
|
+
var activeUIAuthoringService;
|
|
1762
|
+
var UIAuthoringServiceDefinition = createServiceDefinition({
|
|
1763
|
+
id: "kloks.service.uiAuthoring",
|
|
1764
|
+
name: "UIAuthoringService",
|
|
1765
|
+
version: "1.0.0",
|
|
1766
|
+
state: { initial: { sessions: {} } },
|
|
1767
|
+
operations: {
|
|
1768
|
+
createSession: {
|
|
1769
|
+
id: "UIAuthoringService.createSession",
|
|
1770
|
+
name: "createSession",
|
|
1771
|
+
handler: async (input, ctx) => {
|
|
1772
|
+
const sessionId = input.sessionId || `ui-authoring-${Date.now().toString(36)}`;
|
|
1773
|
+
const session = {
|
|
1774
|
+
sessionId,
|
|
1775
|
+
context: input.context,
|
|
1776
|
+
nodes: [],
|
|
1777
|
+
bindings: [],
|
|
1778
|
+
operations: input.operations || [],
|
|
1779
|
+
metadata: input.metadata || {}
|
|
1780
|
+
};
|
|
1781
|
+
activeUIAuthoringService.setState({ sessions: { ...activeUIAuthoringService.getState().sessions, [sessionId]: session } });
|
|
1782
|
+
return session;
|
|
1783
|
+
}
|
|
1784
|
+
},
|
|
1785
|
+
replaceSession: {
|
|
1786
|
+
id: "UIAuthoringService.replaceSession",
|
|
1787
|
+
name: "replaceSession",
|
|
1788
|
+
handler: async (input, ctx) => {
|
|
1789
|
+
if (input.sessionId !== input.session.sessionId) throw new Error("Session id mismatch.");
|
|
1790
|
+
return updateSession(activeUIAuthoringService, input.sessionId, () => input.session);
|
|
1791
|
+
}
|
|
1792
|
+
},
|
|
1793
|
+
addNode: {
|
|
1794
|
+
id: "UIAuthoringService.addNode",
|
|
1795
|
+
name: "addNode",
|
|
1796
|
+
handler: async (input, ctx) => updateSession(activeUIAuthoringService, input.sessionId, (session) => ({
|
|
1797
|
+
...session,
|
|
1798
|
+
nodes: [...session.nodes.filter((node) => node.id !== input.node.id), input.node]
|
|
1799
|
+
}))
|
|
1800
|
+
},
|
|
1801
|
+
updateNode: {
|
|
1802
|
+
id: "UIAuthoringService.updateNode",
|
|
1803
|
+
name: "updateNode",
|
|
1804
|
+
handler: async (input, ctx) => updateSession(activeUIAuthoringService, input.sessionId, (session) => ({
|
|
1805
|
+
...session,
|
|
1806
|
+
nodes: session.nodes.map((node) => node.id === input.nodeId ? { ...node, ...input.patch } : node)
|
|
1807
|
+
}))
|
|
1808
|
+
},
|
|
1809
|
+
removeNode: {
|
|
1810
|
+
id: "UIAuthoringService.removeNode",
|
|
1811
|
+
name: "removeNode",
|
|
1812
|
+
handler: async (input, ctx) => updateSession(activeUIAuthoringService, input.sessionId, (session) => ({
|
|
1813
|
+
...session,
|
|
1814
|
+
nodes: session.nodes.filter((node) => node.id !== input.nodeId && node.parentId !== input.nodeId)
|
|
1815
|
+
}))
|
|
1816
|
+
},
|
|
1817
|
+
setBinding: {
|
|
1818
|
+
id: "UIAuthoringService.setBinding",
|
|
1819
|
+
name: "setBinding",
|
|
1820
|
+
handler: async (input, ctx) => updateSession(activeUIAuthoringService, input.sessionId, (session) => ({
|
|
1821
|
+
...session,
|
|
1822
|
+
bindings: [...session.bindings.filter((binding) => binding.componentId !== input.binding.componentId || binding.property !== input.binding.property), input.binding]
|
|
1823
|
+
}))
|
|
1824
|
+
},
|
|
1825
|
+
setOperations: {
|
|
1826
|
+
id: "UIAuthoringService.setOperations",
|
|
1827
|
+
name: "setOperations",
|
|
1828
|
+
handler: async (input, ctx) => updateSession(activeUIAuthoringService, input.sessionId, (session) => ({ ...session, operations: input.operations }))
|
|
1829
|
+
},
|
|
1830
|
+
validate: {
|
|
1831
|
+
id: "UIAuthoringService.validate",
|
|
1832
|
+
name: "validate",
|
|
1833
|
+
handler: async (input, ctx) => validateSession(getSession(activeUIAuthoringService, input.sessionId))
|
|
1834
|
+
},
|
|
1835
|
+
serialize: {
|
|
1836
|
+
id: "UIAuthoringService.serialize",
|
|
1837
|
+
name: "serialize",
|
|
1838
|
+
handler: async (input, ctx) => JSON.stringify(getSession(activeUIAuthoringService, input.sessionId), null, 2)
|
|
1839
|
+
},
|
|
1840
|
+
generateServiceUI: {
|
|
1841
|
+
id: "UIAuthoringService.generateServiceUI",
|
|
1842
|
+
name: "generateServiceUI",
|
|
1843
|
+
handler: async (input, ctx) => buildServiceUISchema(getSession(activeUIAuthoringService, input.sessionId))
|
|
1844
|
+
},
|
|
1845
|
+
suggestComponent: {
|
|
1846
|
+
id: "UIAuthoringService.suggestComponent",
|
|
1847
|
+
name: "suggestComponent",
|
|
1848
|
+
handler: async (input) => suggestUIComponent(input.fieldType)
|
|
1849
|
+
},
|
|
1850
|
+
getSession: {
|
|
1851
|
+
id: "UIAuthoringService.getSession",
|
|
1852
|
+
name: "getSession",
|
|
1853
|
+
handler: async (input, ctx) => activeUIAuthoringService.getState().sessions[input.sessionId] || null
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
});
|
|
1857
|
+
function getSession(service, sessionId) {
|
|
1858
|
+
const session = service.getState().sessions[sessionId];
|
|
1859
|
+
if (!session) throw new Error(`Unknown UI authoring session: ${sessionId}`);
|
|
1860
|
+
return session;
|
|
1861
|
+
}
|
|
1862
|
+
function updateSession(service, sessionId, update) {
|
|
1863
|
+
const session = update(getSession(service, sessionId));
|
|
1864
|
+
service.setState({ sessions: { ...service.getState().sessions, [sessionId]: session } });
|
|
1865
|
+
return session;
|
|
1866
|
+
}
|
|
1867
|
+
function validateSession(session) {
|
|
1868
|
+
const errors = [];
|
|
1869
|
+
const warnings = [];
|
|
1870
|
+
if (!session.nodes.some((node) => node.kind === "page")) errors.push("At least one page is required.");
|
|
1871
|
+
if (session.nodes.some((node) => node.kind === "component" && !node.assetRef)) errors.push("Every component node requires a FLOKS asset reference.");
|
|
1872
|
+
if (session.context === "service" && !session.metadata.serviceId) errors.push("Service authoring requires metadata.serviceId.");
|
|
1873
|
+
for (const binding of session.bindings) {
|
|
1874
|
+
if (!session.nodes.some((node) => node.id === binding.componentId)) errors.push(`Binding references missing component: ${binding.componentId}`);
|
|
1875
|
+
}
|
|
1876
|
+
if (!session.operations.length) warnings.push("No service operations have been attached to this authoring session.");
|
|
1877
|
+
return { valid: errors.length === 0, errors, warnings };
|
|
1878
|
+
}
|
|
1879
|
+
function createUIAuthoringService() {
|
|
1880
|
+
activeUIAuthoringService = createService(UIAuthoringServiceDefinition);
|
|
1881
|
+
return activeUIAuthoringService;
|
|
1882
|
+
}
|
|
1883
|
+
var defaultUIAuthoringService = createUIAuthoringService();
|
|
1884
|
+
var UIAuthoringServiceFacade = {
|
|
1885
|
+
id: UIAuthoringServiceDefinition.id,
|
|
1886
|
+
name: UIAuthoringServiceDefinition.name,
|
|
1887
|
+
version: UIAuthoringServiceDefinition.version,
|
|
1888
|
+
runtime: "client",
|
|
1889
|
+
deployment: "local",
|
|
1890
|
+
definition: UIAuthoringServiceDefinition,
|
|
1891
|
+
service: defaultUIAuthoringService,
|
|
1892
|
+
createInstance: createUIAuthoringService,
|
|
1893
|
+
execute: async (operation, input) => {
|
|
1894
|
+
await defaultUIAuthoringService.start();
|
|
1895
|
+
return defaultUIAuthoringService.call(operation, input);
|
|
1896
|
+
}
|
|
1897
|
+
};
|
|
1898
|
+
|
|
1654
1899
|
// src/client-services/index.ts
|
|
1655
1900
|
var AuthClientServiceDefinition = createServiceDefinition({
|
|
1656
1901
|
id: "kloks.service.auth",
|
|
@@ -1973,6 +2218,8 @@ export {
|
|
|
1973
2218
|
AuthServiceUISchema,
|
|
1974
2219
|
CLEAN_DATABASE_CLUSTER,
|
|
1975
2220
|
DEFAULT_CONNECTIONS,
|
|
2221
|
+
MonacoIdeServiceDefinition,
|
|
2222
|
+
MonacoIdeServiceFacade,
|
|
1976
2223
|
STORAGE_KEY_CONNECTIONS,
|
|
1977
2224
|
ServiceADefinition,
|
|
1978
2225
|
ServiceAFacade,
|
|
@@ -1990,10 +2237,14 @@ export {
|
|
|
1990
2237
|
SystemDbClientServiceFacade,
|
|
1991
2238
|
SystemDbService,
|
|
1992
2239
|
SystemDbServiceUISchema,
|
|
2240
|
+
UIAuthoringServiceDefinition,
|
|
2241
|
+
UIAuthoringServiceFacade,
|
|
1993
2242
|
authService,
|
|
1994
2243
|
clearSession,
|
|
2244
|
+
createMonacoIdeService,
|
|
1995
2245
|
createServiceB,
|
|
1996
2246
|
createServiceC,
|
|
2247
|
+
createUIAuthoringService,
|
|
1997
2248
|
createWorkspace,
|
|
1998
2249
|
deleteWorkspace,
|
|
1999
2250
|
exposeServiceD,
|
|
@@ -7,6 +7,21 @@ import {
|
|
|
7
7
|
instantiateSubgraph
|
|
8
8
|
} from "./chunk-S22PMERU.js";
|
|
9
9
|
import "./chunk-RHRXPY2U.js";
|
|
10
|
+
import {
|
|
11
|
+
AttractionEngine,
|
|
12
|
+
GhostInferenceEngine,
|
|
13
|
+
GhostLayoutResolver,
|
|
14
|
+
GhostTracePathBuilder,
|
|
15
|
+
calculateSocketCoordinates,
|
|
16
|
+
getBeamPoints,
|
|
17
|
+
useMagneticTraces
|
|
18
|
+
} from "./chunk-JXDJZSFW.js";
|
|
19
|
+
import {
|
|
20
|
+
ConnectionRuleStore,
|
|
21
|
+
HandleTypeRegistry,
|
|
22
|
+
WireTypeRegistry,
|
|
23
|
+
initializeDefaultGraphRules
|
|
24
|
+
} from "./chunk-TZOL3RN7.js";
|
|
10
25
|
import {
|
|
11
26
|
LifecycleCycleError,
|
|
12
27
|
LifecycleGraph,
|
|
@@ -30,21 +45,6 @@ import {
|
|
|
30
45
|
CustomViewWindow,
|
|
31
46
|
DEFAULT_GRAPH_SETTINGS
|
|
32
47
|
} from "./chunk-KG6QYS26.js";
|
|
33
|
-
import {
|
|
34
|
-
AttractionEngine,
|
|
35
|
-
GhostInferenceEngine,
|
|
36
|
-
GhostLayoutResolver,
|
|
37
|
-
GhostTracePathBuilder,
|
|
38
|
-
calculateSocketCoordinates,
|
|
39
|
-
getBeamPoints,
|
|
40
|
-
useMagneticTraces
|
|
41
|
-
} from "./chunk-JXDJZSFW.js";
|
|
42
|
-
import {
|
|
43
|
-
ConnectionRuleStore,
|
|
44
|
-
HandleTypeRegistry,
|
|
45
|
-
WireTypeRegistry,
|
|
46
|
-
initializeDefaultGraphRules
|
|
47
|
-
} from "./chunk-TZOL3RN7.js";
|
|
48
48
|
import {
|
|
49
49
|
AutoSolidify,
|
|
50
50
|
SpatialEngine,
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// src/auth/SessionManager.ts
|
|
2
|
-
var SessionManager = class {
|
|
3
|
-
ttl;
|
|
4
|
-
constructor(ttlMs = 864e5) {
|
|
5
|
-
this.ttl = ttlMs;
|
|
6
|
-
}
|
|
7
|
-
generateToken(userId) {
|
|
8
|
-
return `sess::${userId}::${Date.now()}::${Math.random().toString(36).substring(2, 9)}`;
|
|
9
|
-
}
|
|
10
|
-
createSession(userId, role) {
|
|
11
|
-
return {
|
|
12
|
-
token: this.generateToken(userId),
|
|
13
|
-
userId,
|
|
14
|
-
role,
|
|
15
|
-
expiresAt: Date.now() + this.ttl
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
isValid(session) {
|
|
19
|
-
return Date.now() < session.expiresAt;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// src/auth/RateLimiter.ts
|
|
24
|
-
var RateLimiter = class {
|
|
25
|
-
attempts = /* @__PURE__ */ new Map();
|
|
26
|
-
windowMs;
|
|
27
|
-
maxUser;
|
|
28
|
-
maxAdmin;
|
|
29
|
-
constructor(windowMs = 9e5, maxUser = 5, maxAdmin = 3) {
|
|
30
|
-
this.windowMs = windowMs;
|
|
31
|
-
this.maxUser = maxUser;
|
|
32
|
-
this.maxAdmin = maxAdmin;
|
|
33
|
-
}
|
|
34
|
-
check(identifier, isAdminAttempt = false) {
|
|
35
|
-
const now = Date.now();
|
|
36
|
-
let record = this.attempts.get(identifier);
|
|
37
|
-
if (!record || now - record.windowStart > this.windowMs) {
|
|
38
|
-
record = { count: 0, windowStart: now };
|
|
39
|
-
this.attempts.set(identifier, record);
|
|
40
|
-
}
|
|
41
|
-
record.count++;
|
|
42
|
-
const limit = isAdminAttempt ? this.maxAdmin : this.maxUser;
|
|
43
|
-
if (record.count > limit) {
|
|
44
|
-
throw new Error("Too many requests. Please try again later.");
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
reset(identifier) {
|
|
48
|
-
this.attempts.delete(identifier);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// src/auth/UnifiedAuthCore.ts
|
|
53
|
-
import bcrypt from "bcryptjs";
|
|
54
|
-
async function loginSystemUser(email, rawPass, isAdmin, queryDb) {
|
|
55
|
-
const normEmail = (email || "").trim().toLowerCase();
|
|
56
|
-
const password = (rawPass || "").trim();
|
|
57
|
-
if (!normEmail || !password) {
|
|
58
|
-
return { success: false, status: 400, error: "Email and password are required" };
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
if (isAdmin) {
|
|
62
|
-
const credRes = await queryDb(`SELECT * FROM "ultrst-credentials" WHERE id = 'system' LIMIT 1`, []);
|
|
63
|
-
if (credRes.rows.length > 0) {
|
|
64
|
-
const cred = credRes.rows[0];
|
|
65
|
-
const matchEmail = (cred.admin_email || "").toLowerCase() === normEmail;
|
|
66
|
-
const matchPass = cred.admin_password === password || cred.admin_password && bcrypt.compareSync(password, cred.admin_password);
|
|
67
|
-
if (matchEmail && matchPass) {
|
|
68
|
-
return {
|
|
69
|
-
success: true,
|
|
70
|
-
status: 200,
|
|
71
|
-
token: `adm_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
72
|
-
user: { id: "admin_sys", email: cred.admin_email, username: "System Admin", name: "System Admin", role: "admin", status: "ACTIVE" }
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const uRes = await queryDb(`SELECT * FROM "ultrst-users" WHERE LOWER(email) = $1 LIMIT 1`, [normEmail]);
|
|
78
|
-
if (uRes.rows.length === 0) {
|
|
79
|
-
return { success: false, status: 401, error: "Invalid email or password" };
|
|
80
|
-
}
|
|
81
|
-
const user = uRes.rows[0];
|
|
82
|
-
const hash = user.password_hash || "";
|
|
83
|
-
let isMatch = false;
|
|
84
|
-
if (hash.startsWith("$2a$") || hash.startsWith("$2b$")) {
|
|
85
|
-
isMatch = bcrypt.compareSync(password, hash);
|
|
86
|
-
} else {
|
|
87
|
-
isMatch = hash === password;
|
|
88
|
-
}
|
|
89
|
-
if (!isMatch) {
|
|
90
|
-
return { success: false, status: 401, error: "Invalid email or password" };
|
|
91
|
-
}
|
|
92
|
-
if (isAdmin && user.role !== "admin") {
|
|
93
|
-
return { success: false, status: 403, error: "Insufficient administrative privileges" };
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
success: true,
|
|
97
|
-
status: 200,
|
|
98
|
-
token: `usr_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
99
|
-
user: {
|
|
100
|
-
id: user.id,
|
|
101
|
-
email: user.email,
|
|
102
|
-
username: user.username || user.name || user.email.split("@")[0],
|
|
103
|
-
name: user.name || user.username || "Ecosystem User",
|
|
104
|
-
role: user.role || "user",
|
|
105
|
-
status: user.status || "ACTIVE",
|
|
106
|
-
appProfiles: typeof user.app_profiles === "string" ? JSON.parse(user.app_profiles) : user.app_profiles || {}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
} catch (err) {
|
|
110
|
-
return { success: false, status: 500, error: err.message };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
async function resolveUserFromToken(tokenOrUserId, queryDb) {
|
|
114
|
-
if (!tokenOrUserId) return null;
|
|
115
|
-
let targetId = tokenOrUserId;
|
|
116
|
-
if (targetId.startsWith("Bearer ")) targetId = targetId.slice(7).trim();
|
|
117
|
-
if (targetId.startsWith("sess::")) {
|
|
118
|
-
const parts = targetId.split("::");
|
|
119
|
-
if (parts[1]) targetId = parts[1];
|
|
120
|
-
}
|
|
121
|
-
const res = await queryDb(`SELECT * FROM "ultrst-users" WHERE id = $1 OR LOWER(email) = LOWER($1) LIMIT 1`, [targetId]);
|
|
122
|
-
if (res.rows.length === 0) return null;
|
|
123
|
-
const u = res.rows[0];
|
|
124
|
-
return {
|
|
125
|
-
id: u.id,
|
|
126
|
-
email: u.email,
|
|
127
|
-
username: u.username || u.name || u.email.split("@")[0],
|
|
128
|
-
name: u.name || u.username || "Ecosystem User",
|
|
129
|
-
role: u.role || "user",
|
|
130
|
-
status: u.status || "ACTIVE",
|
|
131
|
-
appProfiles: typeof u.app_profiles === "string" ? JSON.parse(u.app_profiles) : u.app_profiles || {}
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export {
|
|
136
|
-
SessionManager,
|
|
137
|
-
RateLimiter,
|
|
138
|
-
loginSystemUser,
|
|
139
|
-
resolveUserFromToken
|
|
140
|
-
};
|