client online state

This commit is contained in:
manuel.sowada
2026-05-12 07:57:32 +02:00
parent b34f912857
commit 0a28a3e493
17 changed files with 1210 additions and 788 deletions

View File

@@ -552,51 +552,16 @@ GO
CREATE OR ALTER VIEW dbo.vPermissionOverview AS CREATE OR ALTER VIEW dbo.vPermissionOverview AS
SELECT SELECT p.ID AS Permission_ID, p.Scope, p.Resource, p.Action, p.Scope + '.' + p.Resource + '.' + p.Action AS PermissionKey, r.ID AS Role_ID, /* 🔥 NEU: Anzahl Rollen pro Permission*/ COUNT(r.ID) OVER (PARTITION BY p.ID)
p.ID AS Permission_ID, AS RoleCount, COUNT(gr.Group_ObjectGUID) AS GroupCount, COUNT(ar.Authentication_ObjectGUID) AS DirectUserCount, COUNT(ag.Authentication_ObjectGUID) AS GroupUserCount,
p.Scope, COUNT(COALESCE (ar.Authentication_ObjectGUID, ag.Authentication_ObjectGUID)) AS TotalUserCount
p.Resource, FROM dbo.Permission AS p FULL JOIN
p.Action, dbo.RolePermissions AS rp ON rp.Permission_ID = p.ID LEFT JOIN
p.Scope + '.' + p.Resource + '.' + p.Action AS PermissionKey, dbo.Role AS r ON r.ID = rp.Role_ID LEFT JOIN
dbo.GroupRoles AS gr ON gr.Role_ID = r.ID LEFT JOIN
r.ID AS Role_ID, dbo.AuthenticationRoles AS ar ON ar.Role_ID = r.ID LEFT JOIN
dbo.AuthenticationGroups AS ag ON ag.Group_ObjectGUID = gr.Group_ObjectGUID
GROUP BY p.ID, p.Scope, p.Resource, p.Action, r.ID, r.Name;
-- 🔥 NEU: Anzahl Rollen pro Permission
COUNT(r.ID) OVER (PARTITION BY p.ID) AS RoleCount,
COUNT(gr.Group_ObjectGUID) AS GroupCount,
COUNT(ar.Authentication_ObjectGUID) AS DirectUserCount,
COUNT(ag.Authentication_ObjectGUID) AS GroupUserCount,
COUNT(
COALESCE(ar.Authentication_ObjectGUID, ag.Authentication_ObjectGUID)
) AS TotalUserCount
FROM dbo.Permission AS p
INNER JOIN dbo.RolePermissions AS rp
ON rp.Permission_ID = p.ID
INNER JOIN dbo.Role AS r
ON r.ID = rp.Role_ID
LEFT JOIN dbo.GroupRoles AS gr
ON gr.Role_ID = r.ID
LEFT JOIN dbo.AuthenticationRoles AS ar
ON ar.Role_ID = r.ID
LEFT JOIN dbo.AuthenticationGroups AS ag
ON ag.Group_ObjectGUID = gr.Group_ObjectGUID
GROUP BY
p.ID,
p.Scope,
p.Resource,
p.Action,
r.ID,
r.Name;
GO GO

View File

@@ -14,6 +14,7 @@ module.exports = {
localPath, localPath,
cache: { cache: {
startMenuItems: [], startMenuItems: [],
clientsOnline: []
}, },
runtimeFile: { runtimeFile: {
package: new HotReload(path.join(localPath.root, 'package.json')), package: new HotReload(path.join(localPath.root, 'package.json')),

281
package-lock.json generated
View File

@@ -9,7 +9,6 @@
"version": "0.9", "version": "0.9",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"activedirectory2": "^2.2.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"child_process": "^1.0.2", "child_process": "^1.0.2",
@@ -21,7 +20,7 @@
"fs-extra": "^11.3.2", "fs-extra": "^11.3.2",
"https": "^1.0.0", "https": "^1.0.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"ldapjs": "^3.0.7", "ldapts": "^8.1.7",
"module-alias": "^2.2.3", "module-alias": "^2.2.3",
"multer": "^2.0.2", "multer": "^2.0.2",
"net": "^1.0.2", "net": "^1.0.2",
@@ -298,92 +297,6 @@
"resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.5.tgz", "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.5.tgz",
"integrity": "sha512-3zwefSMwHpu8iVUW8YYz227sIv6UFqO31p1Bf1ZH/Vom7CmNyUsXjDBlnNzcuhmOL1XfxZ3nvND42kR23XlbcQ==" "integrity": "sha512-3zwefSMwHpu8iVUW8YYz227sIv6UFqO31p1Bf1ZH/Vom7CmNyUsXjDBlnNzcuhmOL1XfxZ3nvND42kR23XlbcQ=="
}, },
"node_modules/@ldapjs/asn1": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@ldapjs/asn1/-/asn1-2.0.0.tgz",
"integrity": "sha512-G9+DkEOirNgdPmD0I8nu57ygQJKOOgFEMKknEuQvIHbGLwP3ny1mY+OTUYLCbCaGJP4sox5eYgBJRuSUpnAddA==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md"
},
"node_modules/@ldapjs/attribute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@ldapjs/attribute/-/attribute-1.0.0.tgz",
"integrity": "sha512-ptMl2d/5xJ0q+RgmnqOi3Zgwk/TMJYG7dYMC0Keko+yZU6n+oFM59MjQOUht5pxJeS4FWrImhu/LebX24vJNRQ==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "2.0.0",
"@ldapjs/protocol": "^1.2.1",
"process-warning": "^2.1.0"
}
},
"node_modules/@ldapjs/change": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@ldapjs/change/-/change-1.0.0.tgz",
"integrity": "sha512-EOQNFH1RIku3M1s0OAJOzGfAohuFYXFY4s73wOhRm4KFGhmQQ7MChOh2YtYu9Kwgvuq1B0xKciXVzHCGkB5V+Q==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "2.0.0",
"@ldapjs/attribute": "1.0.0"
}
},
"node_modules/@ldapjs/controls": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@ldapjs/controls/-/controls-2.1.0.tgz",
"integrity": "sha512-2pFdD1yRC9V9hXfAWvCCO2RRWK9OdIEcJIos/9cCVP9O4k72BY1bLDQQ4KpUoJnl4y/JoD4iFgM+YWT3IfITWw==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "^1.2.0",
"@ldapjs/protocol": "^1.2.1"
}
},
"node_modules/@ldapjs/controls/node_modules/@ldapjs/asn1": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ldapjs/asn1/-/asn1-1.2.0.tgz",
"integrity": "sha512-KX/qQJ2xxzvO2/WOvr1UdQ+8P5dVvuOLk/C9b1bIkXxZss8BaR28njXdPgFCpj5aHaf1t8PmuVnea+N9YG9YMw==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md"
},
"node_modules/@ldapjs/dn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@ldapjs/dn/-/dn-1.1.0.tgz",
"integrity": "sha512-R72zH5ZeBj/Fujf/yBu78YzpJjJXG46YHFo5E4W1EqfNpo1UsVPqdLrRMXeKIsJT3x9dJVIfR6OpzgINlKpi0A==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "2.0.0",
"process-warning": "^2.1.0"
}
},
"node_modules/@ldapjs/filter": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@ldapjs/filter/-/filter-2.1.1.tgz",
"integrity": "sha512-TwPK5eEgNdUO1ABPBUQabcZ+h9heDORE4V9WNZqCtYLKc06+6+UAJ3IAbr0L0bYTnkkWC/JEQD2F+zAFsuikNw==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "2.0.0",
"@ldapjs/protocol": "^1.2.1",
"process-warning": "^2.1.0"
}
},
"node_modules/@ldapjs/messages": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@ldapjs/messages/-/messages-1.3.0.tgz",
"integrity": "sha512-K7xZpXJ21bj92jS35wtRbdcNrwmxAtPwy4myeh9duy/eR3xQKvikVycbdWVzkYEAVE5Ce520VXNOwCHjomjCZw==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "^2.0.0",
"@ldapjs/attribute": "^1.0.0",
"@ldapjs/change": "^1.0.0",
"@ldapjs/controls": "^2.1.0",
"@ldapjs/dn": "^1.1.0",
"@ldapjs/filter": "^2.1.1",
"@ldapjs/protocol": "^1.2.1",
"process-warning": "^2.2.0"
}
},
"node_modules/@ldapjs/protocol": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@ldapjs/protocol/-/protocol-1.2.1.tgz",
"integrity": "sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md"
},
"node_modules/@socket.io/component-emitter": { "node_modules/@socket.io/component-emitter": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
@@ -455,11 +368,6 @@
"node": ">=6.5" "node": ">=6.5"
} }
}, },
"node_modules/abstract-logging": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
"integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="
},
"node_modules/accepts": { "node_modules/accepts": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
@@ -472,40 +380,6 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/activedirectory2": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/activedirectory2/-/activedirectory2-2.2.0.tgz",
"integrity": "sha512-uGbw74xttFG6hgocU8T1a0oDofLsyTp44BPTn42JN5C2QlyO5kRl2E7ZoUdfpFzV+yxhaQTKI+8QqRB5HONYvA==",
"deprecated": "Decomissioned.",
"dependencies": {
"abstract-logging": "^2.0.0",
"async": "^3.1.0",
"ldapjs": "^2.3.3",
"merge-options": "^2.0.0"
},
"engines": {
"node": ">=4.0"
}
},
"node_modules/activedirectory2/node_modules/ldapjs": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.3.tgz",
"integrity": "sha512-75QiiLJV/PQqtpH+HGls44dXweviFwQ6SiIK27EqzKQ5jU/7UFrl2E5nLdQ3IYRBzJ/AVFJI66u0MZ0uofKYwg==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"abstract-logging": "^2.0.0",
"asn1": "^0.2.4",
"assert-plus": "^1.0.0",
"backoff": "^2.5.0",
"ldap-filter": "^0.3.3",
"once": "^1.4.0",
"vasync": "^2.2.0",
"verror": "^1.8.1"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "7.1.4", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
@@ -541,38 +415,6 @@
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
}, },
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
"integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="
},
"node_modules/backoff": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
"integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==",
"dependencies": {
"precond": "0.2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "4.0.4", "version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -885,11 +727,6 @@
"node": ">=6.6.0" "node": ">=6.6.0"
} }
}, },
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
},
"node_modules/cors": { "node_modules/cors": {
"version": "2.8.5", "version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
@@ -1219,14 +1056,6 @@
"node": ">=22.15.0" "node": ">=22.15.0"
} }
}, },
"node_modules/extsprintf": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
"integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
"engines": [
"node >=0.6.0"
]
},
"node_modules/finalhandler": { "node_modules/finalhandler": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz",
@@ -1558,14 +1387,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-promise": { "node_modules/is-promise": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
@@ -1660,37 +1481,15 @@
"safe-buffer": "^5.0.1" "safe-buffer": "^5.0.1"
} }
}, },
"node_modules/ldap-filter": { "node_modules/ldapts": {
"version": "0.3.3", "version": "8.1.7",
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz", "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-8.1.7.tgz",
"integrity": "sha512-/tFkx5WIn4HuO+6w9lsfxq4FN3O+fDZeO9Mek8dCD8rTUpqzRa766BOBO7BcGkn3X86m5+cBm1/2S/Shzz7gMg==", "integrity": "sha512-TJl6T92eIwMf/OJ0hDfKVa6ISwzo+lqCWCI5Mf//ARlKa3LKQZaSrme/H2rCRBhW0DZCQlrsV+fgoW5YHRNLUw==",
"dependencies": { "dependencies": {
"assert-plus": "^1.0.0" "strict-event-emitter-types": "2.0.0"
}, },
"engines": { "engines": {
"node": ">=0.8" "node": ">=20"
}
},
"node_modules/ldapjs": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-3.0.7.tgz",
"integrity": "sha512-1ky+WrN+4CFMuoekUOv7Y1037XWdjKpu0xAPwSP+9KdvmV9PG+qOKlssDV6a+U32apwxdD3is/BZcWOYzN30cg==",
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
"dependencies": {
"@ldapjs/asn1": "^2.0.0",
"@ldapjs/attribute": "^1.0.0",
"@ldapjs/change": "^1.0.0",
"@ldapjs/controls": "^2.1.0",
"@ldapjs/dn": "^1.1.0",
"@ldapjs/filter": "^2.1.1",
"@ldapjs/messages": "^1.3.0",
"@ldapjs/protocol": "^1.2.1",
"abstract-logging": "^2.0.1",
"assert-plus": "^1.0.0",
"backoff": "^2.5.0",
"once": "^1.4.0",
"vasync": "^2.2.1",
"verror": "^1.10.1"
} }
}, },
"node_modules/lodash": { "node_modules/lodash": {
@@ -1769,17 +1568,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/merge-options": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-options/-/merge-options-2.0.0.tgz",
"integrity": "sha512-S7xYIeWHl2ZUKF7SDeBhGg6rfv5bKxVBdk95s/I7wVF8d+hjLSztJ/B271cnUiF6CAFduEQ5Zn3HYwAjT16DlQ==",
"dependencies": {
"is-plain-obj": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/mime-db": { "node_modules/mime-db": {
"version": "1.54.0", "version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
@@ -3854,14 +3642,6 @@
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
"integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==" "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="
}, },
"node_modules/precond": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
"integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/process": { "node_modules/process": {
"version": "0.11.10", "version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -3870,11 +3650,6 @@
"node": ">= 0.6.0" "node": ">= 0.6.0"
} }
}, },
"node_modules/process-warning": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.3.2.tgz",
"integrity": "sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA=="
},
"node_modules/proxy-addr": { "node_modules/proxy-addr": {
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -4402,6 +4177,11 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/strict-event-emitter-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz",
"integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA=="
},
"node_modules/string_decoder": { "node_modules/string_decoder": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -4629,43 +4409,6 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/vasync": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.1.tgz",
"integrity": "sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"verror": "1.10.0"
}
},
"node_modules/vasync/node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/verror": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
"integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
},
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@@ -21,7 +21,6 @@
"license": "UNLICENSED", "license": "UNLICENSED",
"licensefile": "license_internal.txt", "licensefile": "license_internal.txt",
"dependencies": { "dependencies": {
"activedirectory2": "^2.2.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"body-parser": "^2.2.0", "body-parser": "^2.2.0",
"child_process": "^1.0.2", "child_process": "^1.0.2",
@@ -33,7 +32,7 @@
"fs-extra": "^11.3.2", "fs-extra": "^11.3.2",
"https": "^1.0.0", "https": "^1.0.0",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"ldapjs": "^3.0.7", "ldapts": "^8.1.7",
"module-alias": "^2.2.3", "module-alias": "^2.2.3",
"multer": "^2.0.2", "multer": "^2.0.2",
"net": "^1.0.2", "net": "^1.0.2",

View File

@@ -30,11 +30,13 @@ const RBAC = {
})) }))
.sort((a, b) => a.sAMAccountName.localeCompare(b.sAMAccountName)), .sort((a, b) => a.sAMAccountName.localeCompare(b.sAMAccountName)),
createUser: (data) => api('/api/rbac/auth/create', 'POST', data), createUser: (data) => api('/api/rbac/auth/create', 'POST', data),
syncUsersFromAD: () => api('/api/rbac/auth/syncFromAD', 'POST', { }),
deleteUser: (guid) => api(`/api/rbac/auth/${guid}`, 'DELETE'), deleteUser: (guid) => api(`/api/rbac/auth/${guid}`, 'DELETE'),
// 👥 GROUPS // 👥 GROUPS
loadGroups: () => api('/api/rbac/group/get', 'POST'), loadGroups: () => api('/api/rbac/group/get', 'POST'),
createGroup: (name) => api('/api/rbac/group/create', 'POST', { name }), createGroup: (name) => api('/api/rbac/group/create', 'POST', { name }),
syncGroupsFromAD: () => api('/api/rbac/group/syncFromAD', 'POST', { }),
deleteGroup: (guid) => api(`/api/rbac/group/${guid}`, 'DELETE'), deleteGroup: (guid) => api(`/api/rbac/group/${guid}`, 'DELETE'),
// 🎭 ROLES // 🎭 ROLES
@@ -193,7 +195,7 @@ const rbacPermissionsVT = virtualTable({
data: [], data: [],
rowHeight: 20, rowHeight: 20,
buffer: 5, buffer: 5,
groupKey: 'Scope', groupKey: null,
rowKey: 'ID', rowKey: 'ID',
filterConfig: { filterConfig: {
hideCounter: true, hideCounter: true,
@@ -372,6 +374,13 @@ async function createUser() {
loadUsers(); loadUsers();
} }
async function syncUsersFromAD() {
const users = await RBAC.syncUsersFromAD();
sendUserEvent('RBAC', `${users.length} Benutzer aus dem AD synchronisiert`, null, 0);
loadUsers();
}
async function deleteUser(guid, name) { async function deleteUser(guid, name) {
feedbox({ feedbox({
title: `<span>Benutzer löschen</span>`, title: `<span>Benutzer löschen</span>`,
@@ -420,6 +429,16 @@ async function deleteGroup(guid, name) {
} }
async function syncGroupsFromAD() {
const group = await RBAC.syncGroupsFromAD();
sendUserEvent('RBAC', `${group.length} Gruppen aus dem AD synchronisiert`, null, 0);
loadGroups();
loadUsers();
}
////////////////////////////// //////////////////////////////
// 🎭 ROLE ACTIONS // 🎭 ROLE ACTIONS
////////////////////////////// //////////////////////////////

View File

@@ -43,7 +43,7 @@ button:not(:disabled).yellowbutton:hover { background:var(--theme-button-yellow-
.card.static.row { overflow:hidden; display:flex; flex-direction:row; flex-wrap: wrap;} .card.static.row { overflow:hidden; display:flex; flex-direction:row; flex-wrap: wrap;}
.card.static { overflow:hidden; display:flex; flex-direction:column; } .card.static { overflow:hidden; display:flex; flex-direction:column; }
.container { width:calc(100% - 20px); margin:10px auto; display:grid; grid-template-columns:100%; gap:12px; min-height:0; overflow:auto; max-height:100%; } .container:not(.static) { width:calc(100% - 20px); margin:10px auto; display:grid; grid-template-columns:100%; gap:12px; min-height:0; overflow:auto; max-height:100%; }
.container:not(.static) * { box-sizing:border-box; } .container:not(.static) * { box-sizing:border-box; }
.card { border-width:1px; border-style:solid; border-radius:8px; padding:20px; } .card { border-width:1px; border-style:solid; border-radius:8px; padding:20px; }

View File

@@ -149,4 +149,24 @@
} }
}); });
/* Checks tab visibility
document.addEventListener(
'visibilitychange',
() => {
if (document.hidden) {
alert('AWAY AT: ' + new Date().toISOString());
} else {
updateActivity();
}
}
);
*/
</script> </script>

View File

@@ -29,7 +29,7 @@ section {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 5px; padding: 5px;
width: 120px; width: 200px;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 8px; border-radius: 8px;
margin: 0 2px 2px 0; margin: 0 2px 2px 0;
@@ -62,12 +62,21 @@ input {
</style> </style>
</head> </head>
<body> <body>
<div class="container static" style="max-width:100vw;flex-direction:row;flex-wrap:wrap;flex: 1 1 100vh;">
<!-- USERS --> <!-- USERS -->
<div class="container static" style="height:100vh;max-width:100vw;flex-direction:row;flex-wrap:wrap;"> <div class="card static row" style="align-items:center;height:fit-content;width:100%">
<div class="card" style="flex:1 1 auto;min-width:300px"> AD Synchronisation:
Users <input id="newUserName" placeholder="sAMAccountName" /> <button class="bluebutton" onclick="createUser()">Create User</button> <button class="yellowbutton" data-tooltip="Synchronisiert die Benutzer aus dem AD" onclick="syncUsersFromAD()">Users</button>
<div class="table-wrapper fit-table"> <button class="yellowbutton" data-tooltip="Synchronisiert die Gruppen aus dem AD" onclick="syncGroupsFromAD()">Groups</button>
<table id="rbacUsersTable" style="">
</div>
<div class="card" style="aflex-wrap:wrap;flex: 1 1 100%;justify-content: flex-start;">
Users <input id="newUserName" placeholder="sAMAccountName" />
<button class="bluebutton" onclick="createUser()">Create User</button>
<div class="table-wrapper " style="max-height:300px;overflow:auto">
<table id="rbacUsersTable">
<thead> <thead>
<tr> <tr>
<th class="text-align:left"></th> <th class="text-align:left"></th>
@@ -88,8 +97,30 @@ input {
</div> </div>
</div> </div>
<!-- GROUPS -->
<div class="card static" style="min-width:300px;flex:1 1 calc(300px); max-height: 400px;overflow:auto">
<input id="newGroupName" placeholder="Gruppenname" /> <button class="bluebutton" onclick="createGroup()">Create Group</button>
<div id="rbacGroupContainer">
<span>GRUPPEN WERDEN GELADEN . . .</span>
</div>
</div>
<!-- ROLES -->
<div class="card" style="min-width:300px;flex:1 1 calc(300px)">
<input id="newRoleName" placeholder="Rollenname" />
<button class="bluebutton" onclick="createRole()">Create Role</button>
<div id="rbacRoleContainer">
<span>ROLLEN WERDEN GELADEN . . .</span>
</div>
</div>
<!-- PERMISSIONS --> <!-- PERMISSIONS -->
<div class="card" style="min-width:300px;flex:1 1 auto"> <div class="card" style="min-width:300px;flex:1 1 auto;align-items:center;">
<input id="permScope" placeholder="Scope" />.<input id="permResource" placeholder="Resource" />.<input id="permAction" placeholder="Action" /> <input id="permScope" placeholder="Scope" />.<input id="permResource" placeholder="Resource" />.<input id="permAction" placeholder="Action" />
<button class="bluebutton" onclick="createPermission()">Create Permission</button> <button class="bluebutton" onclick="createPermission()">Create Permission</button>
@@ -115,24 +146,6 @@ input {
</div> </div>
</div> </div>
<!-- GROUPS -->
<div class="card" style="min-width:300px;flex:1 1 calc(300px)">
<input id="newGroupName" placeholder="Gruppenname" /> <button class="bluebutton" onclick="createGroup()">Create Group</button>
<div id="rbacGroupContainer">
<span>GRUPPEN WERDEN GELADEN . . .</span>
</div>
</div>
<!-- ROLES -->
<div class="card" style="min-width:300px;flex:1 1 calc(300px)">
<input id="newRoleName" placeholder="Rollenname" />
<button class="bluebutton" onclick="createRole()">Create Role</button>
<div id="rbacRoleContainer">
<span>ROLLEN WERDEN GELADEN . . .</span>
</div>
</div>
</div> </div>
</body> </body>

View File

@@ -57,7 +57,8 @@ const server = https.createServer(httpsOptions, app);
const io = new Server(server, { const io = new Server(server, {
pingTimeout: 60000, pingInterval: 1000, // alle 25s Ping senden
pingTimeout: 200, // 20s ohne Pong => disconnect
maxHttpBufferSize: 1e8, // 100 MB maxHttpBufferSize: 1e8, // 100 MB
}); });

View File

@@ -12,6 +12,15 @@ module.exports = (sequelize) => {
} }
}, { }, {
tableName: 'AuthenticationGroups', tableName: 'AuthenticationGroups',
indexes: [
{
unique: true,
fields: [
'Authentication_ObjectGUID',
'Group_ObjectGUID'
]
}
],
timestamps: false timestamps: false
}); });

View File

@@ -102,7 +102,6 @@ module.exports = {
app.post('/api/rbac/auth/get', async (req, res) => { app.post('/api/rbac/auth/get', async (req, res) => {
try { try {
console.log(await service.get('rbacManager').syncAuthByActiveDirectory());
rbacUsers = await service.get('rbacManager').getAuth(); rbacUsers = await service.get('rbacManager').getAuth();
res.json(rbacUsers); res.json(rbacUsers);
} catch (err) { } catch (err) {
@@ -138,6 +137,17 @@ module.exports = {
} }
}); });
app.post('/api/rbac/auth/syncFromAD', async (req, res) => {
try {
rbacUsers = await service.get('rbacManager').syncAuthByActiveDirectory();
console.log(await service.get('rbacManager').syncAuthenticationGroupsFromAD());
res.json(rbacUsers);
} catch (err) {
service.get('eventManager').writeLog(req.cookies.ObjectGUID, 4, 'RBAC', err.message);
res.status(500).json({ error: err.message });
}
});
app.put('/api/rbac/auth/:id', async (req, res) => { app.put('/api/rbac/auth/:id', async (req, res) => {
try { try {
await service.get('rbacManager').updateAuth(req.params.id, req.body); await service.get('rbacManager').updateAuth(req.params.id, req.body);
@@ -190,6 +200,17 @@ module.exports = {
} }
}); });
app.post('/api/rbac/group/syncFromAD', async (req, res) => {
try {
console.log(await service.get('rbacManager').syncGroupClosureFromAD());
rbacGroups = await service.get('rbacManager').syncGroupByActiveDirectory();
res.json(rbacGroups);
} catch (err) {
service.get('eventManager').writeLog(req.cookies.ObjectGUID, 4, 'RBAC', err);
res.status(500).json({ error: err.message });
}
});
app.put('/api/rbac/group/:id', async (req, res) => { app.put('/api/rbac/group/:id', async (req, res) => {
try { try {
await service.get('rbacManager').updateGroup(req.params.id, req.body); await service.get('rbacManager').updateGroup(req.params.id, req.body);

File diff suppressed because it is too large Load Diff

View File

@@ -57,6 +57,10 @@ class AuthenticationManager {
return { token: null, levelId: 2, message: 'Falsches Passwort' }; return { token: null, levelId: 2, message: 'Falsches Passwort' };
} }
if(!user.active) {
return { token: null, levelId: 2, message: 'Benutzer nicht aktiv' };
}
const token = jwt.sign( const token = jwt.sign(
{ {
ObjectGUID: user.ObjectGUID, ObjectGUID: user.ObjectGUID,
@@ -67,12 +71,26 @@ class AuthenticationManager {
); );
user.refreshtoken = token; user.refreshtoken = token;
user.online = true; await this.setOnline(sAMAccountName);
await user.save(); await user.save();
return { token, levelId: 0, message: 'Erfolgreich angemeldet' }; return { token, levelId: 0, message: 'Erfolgreich angemeldet' };
} }
async setOnline(sAMAccountName) {
const user = await this.findUser(sAMAccountName);
user.online = true;
await user.save();
}
async setOffline(sAMAccountName) {
const user = await this.findUser(sAMAccountName);
user.online = false;
await user.save();
}
// ========================================================= // =========================================================
// LOGOUT // LOGOUT
// ========================================================= // =========================================================
@@ -85,8 +103,8 @@ class AuthenticationManager {
} }
user.refreshtoken = null; user.refreshtoken = null;
user.online = false;
await user.save(); await user.save();
await this.setOffline();
return { token: null, levelId: 0, message: 'Erfolgreich abgemeldet' }; return { token: null, levelId: 0, message: 'Erfolgreich abgemeldet' };
} }

View File

@@ -190,8 +190,9 @@ class RBACManager {
return res.redirect('/login'); return res.redirect('/login');
} }
const user = await this.db.get('authentication').findOne( { where: { sAMAccountName } } ); req.user = {};
const user = await this.db.get('authentication').findOne( { where: { sAMAccountName } } );
if (!user || !user.active) { if (!user || !user.active) {
return res.redirect('/login'); return res.redirect('/login');
} }
@@ -217,6 +218,7 @@ class RBACManager {
permissions: normalized, permissions: normalized,
isSuperAdmin isSuperAdmin
}; };
next(); next();
} catch (err) { } catch (err) {
@@ -254,19 +256,17 @@ async syncAuthByActiveDirectory() {
const all = await this.service.get('activeDirectoryManager').getAllUsers(); const all = await this.service.get('activeDirectoryManager').getAllUsers();
all.forEach(async user => { all.forEach(async user => {
user.userAccountControl = user.userAccountControl_ID; try {
user.distinguishedName = user.distinguishedName; if(user.objectGUID !== null) {
await auth.upsert({...user, ObjectGUID: user.objectGUID});
await auth.upsert({ } else {
objectGUID: user.ObjectGUID, }
ObjectSource_ID: 2, } catch(err) {
userAccountControl_ID: user.userAccountControl, throw err;
mail: user.mail, }
displayName: user.displayName
});
}) })
// return all; return all;
} }
@@ -319,6 +319,27 @@ async createGroup(data) {
}); });
} }
async syncGroupByActiveDirectory() {
const group = await this.db.get('group');
const all = await this.service.get('activeDirectoryManager').getAllGroups({
attributes: ['objectGUID', 'sAMAccountName', 'distinguishedName'],
includeMembers: false
});
all.forEach(async adGroup => {
try {
if(adGroup.objectGUID !== null) {
await group.upsert({...adGroup, ObjectGUID: adGroup.objectGUID, Name: adGroup.sAMAccountName});
} else {
}
} catch(err) {
throw err;
}
})
return all;
}
async updateGroup(id, data) { async updateGroup(id, data) {
const Group = this.db.get('group'); const Group = this.db.get('group');
@@ -367,6 +388,225 @@ async removeUserFromGroup(authId, groupId) {
}); });
} }
async syncAuthenticationGroupsFromAD() {
const AuthGroups = this.db.get('authenticationGroupsModel');
const users = await this.service
.get('activeDirectoryManager')
.getAllUsers([
'objectGUID',
'memberOf'
]);
const groups = await this.service
.get('activeDirectoryManager')
.getAllGroups({
attributes: [
'objectGUID',
'distinguishedName'
]
});
/**
* -----------------------------------------------------
* GROUP MAP (DN -> GUID)
* -----------------------------------------------------
*/
const groupMap = new Map();
for (const g of groups) {
if (g.distinguishedName && g.objectGUID) {
groupMap.set(
g.distinguishedName.toLowerCase(),
g.objectGUID
);
}
}
/**
* -----------------------------------------------------
* BUILD RELATIONS
* -----------------------------------------------------
*/
const relations = [];
for (const user of users) {
if (!user.objectGUID) continue;
const memberOf = Array.isArray(user.memberOf)
? user.memberOf
: user.memberOf
? [user.memberOf]
: [];
for (const dn of memberOf) {
const groupGuid = groupMap.get(dn.toLowerCase());
if (!groupGuid) continue;
relations.push({
Authentication_ObjectGUID: user.objectGUID,
Group_ObjectGUID: groupGuid
});
}
}
/**
* -----------------------------------------------------
* DB SYNC (clean rebuild)
* -----------------------------------------------------
*/
// await AuthGroups.destroy({
// where: {}
// });
if (relations.length) {
await AuthGroups.upsert(relations, {
// ignoreDuplicates: true
});
}
return relations;
}
async syncGroupClosureFromAD() {
const GroupClosure = this.db.get('groupClosureModel');
const groups = await this.service
.get('activeDirectoryManager')
.getAllGroups({
attributes: [
'objectGUID',
'distinguishedName',
'member'
],
includeMembers: false
});
/**
* -----------------------------------------------------
* MAP: DN -> GUID
* -----------------------------------------------------
*/
const groupMap = new Map();
for (const g of groups) {
if (g.distinguishedName && g.objectGUID) {
groupMap.set(
g.distinguishedName.toLowerCase(),
g.objectGUID
);
}
}
/**
* -----------------------------------------------------
* BUILD DIRECT RELATIONS
* -----------------------------------------------------
*/
const edges = [];
for (const group of groups) {
if (!group.objectGUID) continue;
const members = Array.isArray(group.member)
? group.member
: group.member
? [group.member]
: [];
for (const memberDN of members) {
const childGUID = groupMap.get(
memberDN.toLowerCase()
);
if (!childGUID) continue;
edges.push({
ParentGroup_ObjectGUID: group.objectGUID,
ChildGroup_ObjectGUID: childGUID,
Depth: 1
});
}
}
/**
* -----------------------------------------------------
* TRANSITIVE CLOSURE (DFS)
* -----------------------------------------------------
*/
const closure = [...edges];
const adjacency = new Map();
for (const e of edges) {
if (!adjacency.has(e.ParentGroup_ObjectGUID)) {
adjacency.set(e.ParentGroup_ObjectGUID, []);
}
adjacency.get(e.ParentGroup_ObjectGUID)
.push(e.ChildGroup_ObjectGUID);
}
const visitedCache = new Map();
const dfs = (root, current, depth) => {
const children = adjacency.get(current) || [];
for (const child of children) {
closure.push({
ParentGroup_ObjectGUID: root,
ChildGroup_ObjectGUID: child,
Depth: depth + 1
});
dfs(root, child, depth + 1);
}
};
for (const group of groups) {
const root = group.objectGUID;
if (!root) continue;
dfs(root, root, 0);
}
/**
* -----------------------------------------------------
* CLEAN & SAVE
* -----------------------------------------------------
*/
// await GroupClosure.destroy({
// where: {}
// });
await GroupClosure.bulkCreate(closure, {
ignoreDuplicates: true
});
return closure.length;
}
// ========================================================= // =========================================================
// 🎭 ROLE CRUD // 🎭 ROLE CRUD
// ========================================================= // =========================================================

View File

@@ -25,11 +25,11 @@ class SocketManager {
userName: sAMAccountName userName: sAMAccountName
}); });
// console.log(`${sAMAccountName} [${objectGuid}] connected to ${namespace}`); console.log(`${sAMAccountName} [${objectGuid}] connected to ${namespace}`);
socket.on('disconnect', () => { socket.on('disconnect', () => {
clients.delete(objectGuid); clients.delete(objectGuid);
// console.log(`${sAMAccountName} [${objectGuid}] disconnected from ${namespace}`); console.log(`${sAMAccountName} [${objectGuid}] disconnected from ${namespace}`);
}); });
}); });

View File

@@ -1,5 +1,7 @@
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const { cache } = require('@root/globalize.js');
const { service } = require('@root/server.js');
module.exports = (app, socketManager, namespace, pluginManager, authenticationModel, fileSystemManager, eventManager, activeDirectory) => { module.exports = (app, socketManager, namespace, pluginManager, authenticationModel, fileSystemManager, eventManager, activeDirectory) => {
@@ -12,9 +14,26 @@ module.exports = (app, socketManager, namespace, pluginManager, authenticationMo
// eventManager.write(data.objectGuid, data.levelId, data.pluginName, data.message) // eventManager.write(data.objectGuid, data.levelId, data.pluginName, data.message)
}); });
// global.json.configuration.onChange(info => {
// console.log(info.delta)
// }); socketManager.io.on('connection', async (socket) => {
if(!socket.handshake.auth.objectGuid) {
return;
}
await service.get('authenticationManager').setOnline(socket.handshake.auth.sAMAccountName);
});
socketManager.on(namespace, 'disconnect', (socket, data) => {
if(!socket.handshake.auth.objectGuid) {
return;
}
setTimeout(async () => {
if(!socketManager.clients.get(namespace).has(socket.handshake.auth.objectGuid)) {
await service.get('authenticationManager').setOffline(socket.handshake.auth.sAMAccountName);
}
}, 8000);
});
mainSocket.on('connection', socket => { mainSocket.on('connection', socket => {