Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions server/basedir-includes/configure-from-env
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ while read -r keyvalue; do
ACTUAL_KEY="${ACTUAL_KEY//_/.}"

# lower case
# example: database.max-connections
ACTUAL_KEY="${ACTUAL_KEY,,}"
# example: database.max-connections (but not _MP_user_pref_default_showTags)
if [[ ! ${ACTUAL_KEY} =~ [a-z] ]]; then
ACTUAL_KEY="${ACTUAL_KEY,,}"
fi
Comment thread
mgaffigan marked this conversation as resolved.

# if key does not exist in mirth.properties append it at bottom
LINE_COUNT=`grep "^${ACTUAL_KEY}" "$APP_DIR/conf/mirth.properties" | wc -l`
Expand Down
7 changes: 7 additions & 0 deletions server/src/com/mirth/connect/model/AdminUserPreference.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 Mitch Gaffigan

package com.mirth.connect.model;

/** Administrative policy for a user preference */
public record AdminUserPreference(String value, boolean locked) {}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.mirth.commons.encryption.Digester;
import com.mirth.commons.encryption.Encryptor;
import com.mirth.connect.client.core.ControllerException;
import com.mirth.connect.model.AdminUserPreference;
import com.mirth.connect.model.ChannelDependency;
import com.mirth.connect.model.ChannelMetadata;
import com.mirth.connect.model.ChannelTag;
Expand Down Expand Up @@ -335,6 +336,9 @@ public Properties getPropertiesForGroup(String group) {

public abstract Properties getPropertiesForGroup(String group, Set<String> propertyKeys);

/** Get administratively set user preferences */
public abstract Map<String, AdminUserPreference> getUserPreferenceProperties();

public abstract void removePropertiesForGroup(String group);

public abstract String getProperty(String group, String name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import com.mirth.connect.donkey.model.DatabaseConstants;
import com.mirth.connect.donkey.server.data.DonkeyStatisticsUpdater;
import com.mirth.connect.donkey.util.DonkeyElement;
import com.mirth.connect.model.AdminUserPreference;
import com.mirth.connect.model.Channel;
import com.mirth.connect.model.ChannelDependency;
import com.mirth.connect.model.ChannelMetadata;
Expand Down Expand Up @@ -144,6 +145,8 @@ public class DefaultConfigurationController extends ConfigurationController {
public static final String PROPERTIES_CHANNEL_METADATA = "channelMetadata";
public static final String PROPERTIES_CHANNEL_TAGS = "channelTags";
public static final String PROPERTIES_DATABASE_DRIVERS = "databaseDrivers";
private static final String USER_PREFERENCE_DEFAULT_PREFIX = "user.pref.default.";
private static final String USER_PREFERENCE_LOCK_PREFIX = "user.pref.lock.";
public static final String SECRET_KEY_ALIAS = "encryption";
public static final String VACUUM_LOCK_STATEMENT_ID = "Configuration.vacuumConfigurationTable";

Expand Down Expand Up @@ -1002,6 +1005,26 @@ public Properties getPropertiesForGroup(String category, Set<String> propertyKey
return properties;
}

@Override
public Map<String, AdminUserPreference> getUserPreferenceProperties() {
Properties coreProperties = getPropertiesForGroup(PROPERTIES_CORE);
Map<String, AdminUserPreference> policies = new HashMap<String, AdminUserPreference>();

for (String key : coreProperties.stringPropertyNames()) {
if (!key.startsWith(USER_PREFERENCE_DEFAULT_PREFIX)) {
continue;
}

Comment thread
mgaffigan marked this conversation as resolved.
String preferenceName = key.substring(USER_PREFERENCE_DEFAULT_PREFIX.length());
String value = coreProperties.getProperty(key);
boolean locked = Boolean.parseBoolean(coreProperties.getProperty(USER_PREFERENCE_LOCK_PREFIX + preferenceName));

policies.put(preferenceName, new AdminUserPreference(value, locked));
}

return policies;
}

public void removePropertiesForGroup(String category) {
logger.debug("deleting all properties: category=" + category);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import com.mirth.commons.encryption.Digester;
import com.mirth.connect.client.core.ControllerException;
import com.mirth.connect.model.AdminUserPreference;
import com.mirth.connect.model.Credentials;
import com.mirth.connect.model.LoginStatus;
import com.mirth.connect.model.LoginStatus.Status;
Expand Down Expand Up @@ -560,11 +561,23 @@ public Properties getUserPreferences(Integer userId, Set<String> names) {
logger.debug("retrieving preferences: user id=" + userId);
Properties properties = new Properties();

var policies = ControllerFactory.getFactory().createConfigurationController().getUserPreferenceProperties();
for (var entry : policies.entrySet()) {
if (CollectionUtils.isEmpty(names) || names.contains(entry.getKey())) {
properties.setProperty(entry.getKey(), StringUtils.defaultString(entry.getValue().value()));
}
}

StatementLock.getInstance(VACUUM_LOCK_PREFERENCES_STATEMENT_ID).readLock();
try {
List<KeyValuePair> result = SqlConfig.getInstance().getReadOnlySqlSessionManager().selectList("User.selectPreferencesForUser", userId);

for (KeyValuePair pair : result) {
var policy = policies.get(pair.getKey());
if (policy != null && policy.locked()) {
continue;
}
Comment thread
mgaffigan marked this conversation as resolved.

if (CollectionUtils.isEmpty(names) || names.contains(pair.getKey())) {
properties.setProperty(pair.getKey(), StringUtils.defaultString(pair.getValue()));
}
Expand All @@ -582,6 +595,14 @@ public Properties getUserPreferences(Integer userId, Set<String> names) {
public String getUserPreference(Integer userId, String name) {
logger.debug("retrieving preference: user id=" + userId + ", name=" + name);

var policy = ControllerFactory.getFactory().createConfigurationController().getUserPreferenceProperties().get(name);
policy = policy != null ? policy : new AdminUserPreference(null, false);

String value = policy.value();
if (policy.locked()) {
return value;
}
Comment on lines +598 to +604

StatementLock.getInstance(VACUUM_LOCK_PREFERENCES_STATEMENT_ID).readLock();
try {
Map<String, Object> parameterMap = new HashMap<String, Object>();
Expand Down
Loading