@strapi-community/plugin-io 5.2.0 → 5.3.1
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/README.md +23 -21
- package/dist/_chunks/{LivePresencePanel-2U3I3yL0.js → LivePresencePanel-BkeWL4kq.js} +1 -1
- package/dist/_chunks/{LivePresencePanel-CIFG_05s.mjs → LivePresencePanel-D_vzQr4B.mjs} +1 -1
- package/dist/_chunks/{MonitoringPage-9f4Gzd2X.js → MonitoringPage-CYGqkzva.js} +1 -1
- package/dist/_chunks/{MonitoringPage-Bbkoh6ih.mjs → MonitoringPage-DKfhYUgU.mjs} +1 -1
- package/dist/_chunks/OnlineEditorsWidget-Bf8hfVha.js +341 -0
- package/dist/_chunks/OnlineEditorsWidget-RcYLxQke.mjs +339 -0
- package/dist/_chunks/{SettingsPage-CsRazf0j.js → SettingsPage-0k9qPAJZ.js} +1 -1
- package/dist/_chunks/{SettingsPage-Btz_5MuC.mjs → SettingsPage-Qi0iMaWc.mjs} +1 -1
- package/dist/_chunks/{index-Dof_eA3e.mjs → index-Bw7WjN5H.mjs} +17 -4
- package/dist/_chunks/{index-BEZDDgvZ.js → index-DVNfszio.js} +17 -4
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +137 -7
- package/dist/server/index.mjs +137 -7
- package/package.json +1 -1
package/dist/server/index.mjs
CHANGED
|
@@ -634,7 +634,9 @@ async function bootstrapIO$1({ strapi: strapi2 }) {
|
|
|
634
634
|
});
|
|
635
635
|
socket.on("get-entity-subscriptions", (callback) => {
|
|
636
636
|
const rooms = Array.from(socket.rooms).filter((r) => r !== socket.id && r.includes(":")).map((room) => {
|
|
637
|
-
const
|
|
637
|
+
const lastColonIndex = room.lastIndexOf(":");
|
|
638
|
+
const uid = room.substring(0, lastColonIndex);
|
|
639
|
+
const id = room.substring(lastColonIndex + 1);
|
|
638
640
|
return { uid, id, room };
|
|
639
641
|
});
|
|
640
642
|
if (callback) callback({ success: true, subscriptions: rooms });
|
|
@@ -1316,7 +1318,7 @@ const sessionTokens = /* @__PURE__ */ new Map();
|
|
|
1316
1318
|
const activeSockets = /* @__PURE__ */ new Map();
|
|
1317
1319
|
const refreshThrottle = /* @__PURE__ */ new Map();
|
|
1318
1320
|
const SESSION_TTL = 10 * 60 * 1e3;
|
|
1319
|
-
const REFRESH_COOLDOWN =
|
|
1321
|
+
const REFRESH_COOLDOWN = 3 * 1e3;
|
|
1320
1322
|
const CLEANUP_INTERVAL = 2 * 60 * 1e3;
|
|
1321
1323
|
const hashToken = (token) => {
|
|
1322
1324
|
return createHash("sha256").update(token).digest("hex");
|
|
@@ -1367,7 +1369,7 @@ var presence$3 = ({ strapi: strapi2 }) => ({
|
|
|
1367
1369
|
userId: adminUser.id,
|
|
1368
1370
|
user: {
|
|
1369
1371
|
id: adminUser.id,
|
|
1370
|
-
|
|
1372
|
+
email: adminUser.email,
|
|
1371
1373
|
firstname: adminUser.firstname,
|
|
1372
1374
|
lastname: adminUser.lastname
|
|
1373
1375
|
},
|
|
@@ -1530,6 +1532,32 @@ var presence$3 = ({ strapi: strapi2 }) => ({
|
|
|
1530
1532
|
strapi2.log.error("[plugin-io] Failed to invalidate user sessions:", error2);
|
|
1531
1533
|
return ctx.internalServerError("Failed to invalidate sessions");
|
|
1532
1534
|
}
|
|
1535
|
+
},
|
|
1536
|
+
/**
|
|
1537
|
+
* HTTP Handler: Gets all online users with their editing info
|
|
1538
|
+
* Used for the "Who's Online" dashboard widget
|
|
1539
|
+
* @param {object} ctx - Koa context
|
|
1540
|
+
*/
|
|
1541
|
+
async getOnlineUsers(ctx) {
|
|
1542
|
+
const adminUser = ctx.state.user;
|
|
1543
|
+
if (!adminUser) {
|
|
1544
|
+
return ctx.unauthorized("Admin authentication required");
|
|
1545
|
+
}
|
|
1546
|
+
try {
|
|
1547
|
+
const presenceService = strapi2.plugin("io").service("presence");
|
|
1548
|
+
const onlineUsers = presenceService.getOnlineUsers();
|
|
1549
|
+
const counts = presenceService.getOnlineCounts();
|
|
1550
|
+
ctx.body = {
|
|
1551
|
+
data: {
|
|
1552
|
+
users: onlineUsers,
|
|
1553
|
+
counts,
|
|
1554
|
+
timestamp: Date.now()
|
|
1555
|
+
}
|
|
1556
|
+
};
|
|
1557
|
+
} catch (error2) {
|
|
1558
|
+
strapi2.log.error("[plugin-io] Failed to get online users:", error2);
|
|
1559
|
+
return ctx.internalServerError("Failed to get online users");
|
|
1560
|
+
}
|
|
1533
1561
|
}
|
|
1534
1562
|
});
|
|
1535
1563
|
const settings$2 = settings$3;
|
|
@@ -1639,6 +1667,15 @@ var admin$1 = {
|
|
|
1639
1667
|
config: {
|
|
1640
1668
|
policies: ["admin::isAuthenticatedAdmin"]
|
|
1641
1669
|
}
|
|
1670
|
+
},
|
|
1671
|
+
// Who's Online: Get all online users with editing info
|
|
1672
|
+
{
|
|
1673
|
+
method: "GET",
|
|
1674
|
+
path: "/online-users",
|
|
1675
|
+
handler: "presence.getOnlineUsers",
|
|
1676
|
+
config: {
|
|
1677
|
+
policies: ["admin::isAuthenticatedAdmin"]
|
|
1678
|
+
}
|
|
1642
1679
|
}
|
|
1643
1680
|
]
|
|
1644
1681
|
};
|
|
@@ -11314,6 +11351,7 @@ const getNonVisibleAttributes = (model) => {
|
|
|
11314
11351
|
return ___default.uniq([
|
|
11315
11352
|
ID_ATTRIBUTE$4,
|
|
11316
11353
|
DOC_ID_ATTRIBUTE$4,
|
|
11354
|
+
PUBLISHED_AT_ATTRIBUTE$1,
|
|
11317
11355
|
...getTimestamps(model),
|
|
11318
11356
|
...nonVisibleAttributes
|
|
11319
11357
|
]);
|
|
@@ -30518,7 +30556,10 @@ var presence$1 = ({ strapi: strapi2 }) => {
|
|
|
30518
30556
|
*/
|
|
30519
30557
|
registerConnection(socketId, user = null) {
|
|
30520
30558
|
const settings2 = getPresenceSettings();
|
|
30521
|
-
if (!settings2.enabled)
|
|
30559
|
+
if (!settings2.enabled) {
|
|
30560
|
+
strapi2.log.warn(`socket.io: Presence disabled, skipping registration for ${socketId}`);
|
|
30561
|
+
return;
|
|
30562
|
+
}
|
|
30522
30563
|
activeConnections.set(socketId, {
|
|
30523
30564
|
user,
|
|
30524
30565
|
entities: /* @__PURE__ */ new Map(),
|
|
@@ -30526,7 +30567,8 @@ var presence$1 = ({ strapi: strapi2 }) => {
|
|
|
30526
30567
|
lastSeen: Date.now(),
|
|
30527
30568
|
connectedAt: Date.now()
|
|
30528
30569
|
});
|
|
30529
|
-
|
|
30570
|
+
const username = user?.username || user?.firstname || "anonymous";
|
|
30571
|
+
strapi2.log.info(`socket.io: Presence registered for ${username} (socket: ${socketId}, total: ${activeConnections.size})`);
|
|
30530
30572
|
},
|
|
30531
30573
|
/**
|
|
30532
30574
|
* Unregisters a socket connection and cleans up all entity presence
|
|
@@ -30537,7 +30579,9 @@ var presence$1 = ({ strapi: strapi2 }) => {
|
|
|
30537
30579
|
if (!connection) return;
|
|
30538
30580
|
if (connection.entities) {
|
|
30539
30581
|
for (const entityKey of connection.entities.keys()) {
|
|
30540
|
-
const
|
|
30582
|
+
const lastColonIndex = entityKey.lastIndexOf(":");
|
|
30583
|
+
const uid = entityKey.substring(0, lastColonIndex);
|
|
30584
|
+
const documentId = entityKey.substring(lastColonIndex + 1);
|
|
30541
30585
|
await this.leaveEntity(socketId, uid, documentId, false);
|
|
30542
30586
|
}
|
|
30543
30587
|
}
|
|
@@ -30772,6 +30816,90 @@ var presence$1 = ({ strapi: strapi2 }) => {
|
|
|
30772
30816
|
timestamp: Date.now()
|
|
30773
30817
|
});
|
|
30774
30818
|
}
|
|
30819
|
+
},
|
|
30820
|
+
/**
|
|
30821
|
+
* Gets all online users with their currently editing entities
|
|
30822
|
+
* Used for the "Who's Online" dashboard widget
|
|
30823
|
+
* @returns {Array} List of online users with their editing info
|
|
30824
|
+
*/
|
|
30825
|
+
getOnlineUsers() {
|
|
30826
|
+
const users = [];
|
|
30827
|
+
const now = Date.now();
|
|
30828
|
+
for (const [socketId, connection] of activeConnections) {
|
|
30829
|
+
if (!connection.user) continue;
|
|
30830
|
+
const editingEntities = [];
|
|
30831
|
+
if (connection.entities) {
|
|
30832
|
+
for (const [entityKey, joinedAt] of connection.entities) {
|
|
30833
|
+
const lastColonIndex = entityKey.lastIndexOf(":");
|
|
30834
|
+
const uid = entityKey.substring(0, lastColonIndex);
|
|
30835
|
+
const documentId = entityKey.substring(lastColonIndex + 1);
|
|
30836
|
+
let contentTypeName = uid;
|
|
30837
|
+
try {
|
|
30838
|
+
const contentType = strapi2.contentTypes[uid];
|
|
30839
|
+
if (contentType?.info?.displayName) {
|
|
30840
|
+
contentTypeName = contentType.info.displayName;
|
|
30841
|
+
} else if (contentType?.info?.singularName) {
|
|
30842
|
+
contentTypeName = contentType.info.singularName;
|
|
30843
|
+
}
|
|
30844
|
+
} catch (e) {
|
|
30845
|
+
}
|
|
30846
|
+
editingEntities.push({
|
|
30847
|
+
uid,
|
|
30848
|
+
documentId,
|
|
30849
|
+
contentTypeName,
|
|
30850
|
+
joinedAt,
|
|
30851
|
+
editingFor: Math.floor((now - joinedAt) / 1e3)
|
|
30852
|
+
// seconds
|
|
30853
|
+
});
|
|
30854
|
+
}
|
|
30855
|
+
}
|
|
30856
|
+
users.push({
|
|
30857
|
+
socketId,
|
|
30858
|
+
user: {
|
|
30859
|
+
id: connection.user.id,
|
|
30860
|
+
username: connection.user.username,
|
|
30861
|
+
email: connection.user.email,
|
|
30862
|
+
firstname: connection.user.firstname,
|
|
30863
|
+
lastname: connection.user.lastname,
|
|
30864
|
+
isAdmin: connection.user.isAdmin || false
|
|
30865
|
+
},
|
|
30866
|
+
connectedAt: connection.connectedAt,
|
|
30867
|
+
lastSeen: connection.lastSeen,
|
|
30868
|
+
onlineFor: Math.floor((now - connection.connectedAt) / 1e3),
|
|
30869
|
+
// seconds
|
|
30870
|
+
editingEntities,
|
|
30871
|
+
isEditing: editingEntities.length > 0
|
|
30872
|
+
});
|
|
30873
|
+
}
|
|
30874
|
+
users.sort((a, b) => {
|
|
30875
|
+
if (a.isEditing && !b.isEditing) return -1;
|
|
30876
|
+
if (!a.isEditing && b.isEditing) return 1;
|
|
30877
|
+
return b.connectedAt - a.connectedAt;
|
|
30878
|
+
});
|
|
30879
|
+
return users;
|
|
30880
|
+
},
|
|
30881
|
+
/**
|
|
30882
|
+
* Gets count of online users
|
|
30883
|
+
* @returns {object} Online user counts
|
|
30884
|
+
*/
|
|
30885
|
+
getOnlineCounts() {
|
|
30886
|
+
let total = 0;
|
|
30887
|
+
let admins = 0;
|
|
30888
|
+
let users = 0;
|
|
30889
|
+
let editing = 0;
|
|
30890
|
+
for (const connection of activeConnections.values()) {
|
|
30891
|
+
if (!connection.user) continue;
|
|
30892
|
+
total++;
|
|
30893
|
+
if (connection.user.isAdmin) {
|
|
30894
|
+
admins++;
|
|
30895
|
+
} else {
|
|
30896
|
+
users++;
|
|
30897
|
+
}
|
|
30898
|
+
if (connection.entities?.size > 0) {
|
|
30899
|
+
editing++;
|
|
30900
|
+
}
|
|
30901
|
+
}
|
|
30902
|
+
return { total, admins, users, editing };
|
|
30775
30903
|
}
|
|
30776
30904
|
};
|
|
30777
30905
|
};
|
|
@@ -30988,7 +31116,9 @@ var preview$1 = ({ strapi: strapi2 }) => {
|
|
|
30988
31116
|
getActivePreviewEntities() {
|
|
30989
31117
|
const entities = [];
|
|
30990
31118
|
for (const [entityKey, subscribers] of previewSubscribers) {
|
|
30991
|
-
const
|
|
31119
|
+
const lastColonIndex = entityKey.lastIndexOf(":");
|
|
31120
|
+
const uid = entityKey.substring(0, lastColonIndex);
|
|
31121
|
+
const documentId = entityKey.substring(lastColonIndex + 1);
|
|
30992
31122
|
entities.push({
|
|
30993
31123
|
uid,
|
|
30994
31124
|
documentId,
|
package/package.json
CHANGED