Release v2.11.1
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m47s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 31s

This commit is contained in:
2026-09-04 15:43:55 +01:00
parent 2c150b5b2e
commit 98f969ca0f
104 changed files with 3559 additions and 447 deletions
+1
View File
@@ -2,5 +2,6 @@
module.exports = {
createSessionService: require('./session').createSessionService,
getRequestOrigin: require('./session').getRequestOrigin,
rbacData: require('./rbac-data')
};
+29 -2
View File
@@ -57,6 +57,32 @@ async function fetchRolesPage(pool, page, pageSize, searchTerm, sortKey, sortDir
return Object.assign({ roles: paged.rows }, paged);
}
async function fetchInvitationsPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) {
const paged = await fetchPagedRows(pool, {
selectSql: `SELECT i.id, i.email, i.name, i.role_ids_json, i.created_at, i.expires_at, u.username AS created_by_username
FROM a_user_invitations i
LEFT JOIN a_users u ON u.id = i.created_by
WHERE i.used_at IS NULL AND i.expires_at > NOW()
ORDER BY i.created_at DESC`,
countSql: 'SELECT COUNT(*) AS count FROM a_user_invitations WHERE used_at IS NULL AND expires_at > NOW()',
searchColumns: ['i.email', 'i.name', 'u.username'],
searchTerm: searchTerm,
sortColumns: {
email: 'i.email',
name: 'i.name',
created: 'i.created_at',
expires: 'i.expires_at',
createdBy: 'u.username'
},
sortKey: sortKey,
sortDirection: sortDirection,
page: page,
pageSize: pageSize
});
return Object.assign({ invitations: paged.rows }, paged);
}
async function fetchRoleById(pool, roleId) {
const [rows] = await pool.query(
`SELECT r.id, r.role_key, r.name, r.description, r.created_at, r.modified_at,
@@ -142,7 +168,7 @@ async function fetchUsersWithRolesPage(pool, page, pageSize, searchTerm, sortKey
const whereSql = hasExcludedUserId ? 'WHERE u.id <> ?' : '';
const queryArgs = hasExcludedUserId ? [excludedUserId] : [];
const paged = await fetchPagedRows(pool, {
selectSql: `SELECT u.id, u.name, u.username, u.account_locked, u.created_at, u.modified_at,
selectSql: `SELECT u.id, u.name, u.username, u.email, u.email_verified_at, u.account_locked, u.created_at, u.modified_at,
COALESCE(role_data.role_names, '') AS role_names,
COALESCE(role_data.role_ids_csv, '') AS role_ids_csv
FROM a_users u
@@ -189,7 +215,7 @@ async function fetchUsersWithRolesPage(pool, page, pageSize, searchTerm, sortKey
async function fetchUserWithRoles(pool, userId) {
const [rows] = await pool.query(
`SELECT u.id, u.name, u.username, u.account_locked, u.created_at, u.modified_at,
`SELECT u.id, u.name, u.username, u.email, u.email_verified_at, u.account_locked, u.created_at, u.modified_at,
COALESCE(role_data.role_names, '') AS role_names,
COALESCE(role_data.role_ids_csv, '') AS role_ids_csv
FROM a_users u
@@ -299,6 +325,7 @@ module.exports = {
fetchPermissions,
fetchRoles,
fetchRolesPage,
fetchInvitationsPage,
fetchRoleById,
fetchRolePermissionKeys,
fetchRoleUserIds,
+1 -1
View File
@@ -128,7 +128,7 @@ function createSessionService(options) {
const tokenHash = hashSessionToken(token);
const [rows] = await pool.query(
`SELECT s.user_id, u.id, u.name, u.username, u.must_change_password
`SELECT s.user_id, u.id, u.name, u.username, u.email, u.email_verified_at, u.pending_email, u.must_change_password
FROM a_sessions s
JOIN a_users u ON u.id = s.user_id
WHERE s.session_hash = ?
+3
View File
@@ -184,6 +184,9 @@ function substitutePlaceholders(html, regionContent, options) {
const resolved = typeof placeholderUtils.resolvePlaceholderExpression === 'function'
? placeholderUtils.resolvePlaceholderExpression(item, weatherExpression, { timeZone: item.timezone })
: resolvePlaceholderPath(item, expression);
if (typeof placeholderUtils.isProgressPlaceholderExpression === 'function' && placeholderUtils.isProgressPlaceholderExpression(expression)) {
return placeholderUtils.renderProgressPlaceholder(item, expression);
}
if (type === 'weather' && /(?:^|\.)weather_code\.\d+\.icon(?:\(|$)|^current\.weather_code\.icon/.test(weatherExpression)) {
const codeExpression = weatherExpression.replace(/\.icon(?:\(.*\))?$/, '');
const iconSize = String(expression).match(/\.icon\(\s*(\d+)(?:\s*,\s*(\d+))?\s*\)$/);