use of org.openremote.model.query.UserQuery in project openremote by openremote.
the class ManagerIdentityProvider method getUsersFromDb.
static User[] getUsersFromDb(PersistenceService persistenceService, UserQuery query) {
StringBuilder sb = new StringBuilder();
List<Object> parameters = new ArrayList<>();
final UserQuery userQuery = query != null ? query : new UserQuery();
// BUILD SELECT
sb.append("SELECT u");
// BUILD FROM
sb.append(" FROM User u");
if (userQuery.assetPredicate != null || userQuery.pathPredicate != null) {
sb.append(" join UserAssetLink ua on ua.id.userId = u.id");
}
// BUILD WHERE
sb.append(" WHERE 1=1");
if (userQuery.tenantPredicate != null && !TextUtil.isNullOrEmpty(userQuery.tenantPredicate.realm)) {
sb.append(" AND u.realm = ?").append(parameters.size() + 1);
parameters.add(userQuery.tenantPredicate.realm);
}
if (userQuery.assetPredicate != null) {
sb.append(" AND ua.id.assetId = ?").append(parameters.size() + 1);
parameters.add(userQuery.assetPredicate.id);
}
if (userQuery.pathPredicate != null) {
sb.append(" AND ?").append(parameters.size() + 1).append(" <@ get_asset_tree_path(ua.asset_id)");
parameters.add(userQuery.pathPredicate.path);
}
if (userQuery.ids != null && userQuery.ids.length > 0) {
sb.append(" AND u.id IN (?").append(parameters.size() + 1);
parameters.add(userQuery.ids[0]);
for (int i = 1; i < userQuery.ids.length; i++) {
sb.append(",?").append(parameters.size() + 1);
parameters.add(userQuery.ids[i]);
}
sb.append(")");
}
if (userQuery.usernames != null && userQuery.usernames.length > 0) {
sb.append(" and (");
boolean isFirst = true;
for (StringPredicate pred : userQuery.usernames) {
if (!isFirst) {
sb.append(" or ");
}
isFirst = false;
final int pos = parameters.size() + 1;
// No case support for username
sb.append("upper(u.username)");
sb.append(buildMatchFilter(pred, pos));
parameters.add(pred.prepareValue());
}
sb.append(")");
}
if (userQuery.select != null && userQuery.select.excludeRegularUsers) {
sb.append(" and u.secret IS NOT NULL");
} else if (userQuery.select != null && userQuery.select.excludeServiceUsers) {
sb.append(" and u.secret IS NULL");
}
// BUILD ORDER BY
if (userQuery.orderBy != null) {
if (userQuery.orderBy.property != null) {
sb.append(" ORDER BY");
switch(userQuery.orderBy.property) {
case CREATED_ON:
sb.append(" u.createdOn");
break;
case FIRST_NAME:
sb.append(" u.firstName");
break;
case LAST_NAME:
sb.append(" u.lastName");
break;
case USERNAME:
// Remove service user prefix
sb.append(" replace(u.username, '").append(User.SERVICE_ACCOUNT_PREFIX).append("', '')");
break;
case EMAIL:
sb.append(" u.email");
break;
default:
throw new UnsupportedOperationException("Unsupported order by value: " + userQuery.orderBy.property);
}
if (userQuery.orderBy.descending) {
sb.append(" DESC");
}
}
}
List<User> users = persistenceService.doReturningTransaction(entityManager -> {
TypedQuery<User> sqlQuery = entityManager.createQuery(sb.toString(), User.class);
IntStream.range(0, parameters.size()).forEach(i -> sqlQuery.setParameter(i + 1, parameters.get(i)));
if (userQuery.limit != null && userQuery.limit > 0) {
sqlQuery.setMaxResults(userQuery.limit);
}
if (userQuery.offset != null && userQuery.offset > 0) {
sqlQuery.setFirstResult(query.offset);
}
return sqlQuery.getResultList();
});
if (userQuery.select != null && (userQuery.select.basic || userQuery.select.excludeSystemUsers)) {
// TODO: Move this within the query
return users.stream().filter(user -> {
boolean keep = !userQuery.select.excludeSystemUsers || !user.isSystemAccount();
if (keep && userQuery.select.basic) {
// Clear out data and leave only basic info
user.setAttributes(null);
user.setEmail(null);
user.setRealmId(null);
user.setSecret(null);
}
return keep;
}).toArray(User[]::new);
}
return users.toArray(new User[0]);
}
use of org.openremote.model.query.UserQuery in project openremote by openremote.
the class ManagerKeycloakIdentityProvider method queryUsers.
@Override
public User[] queryUsers(UserQuery userQuery) {
if (userQuery == null) {
userQuery = new UserQuery();
}
if (userQuery.usernames == null) {
userQuery.usernames = new StringPredicate[1];
userQuery.usernames(new StringPredicate(AssetQuery.Match.BEGIN, User.SERVICE_ACCOUNT_PREFIX).negate(true));
} else {
userQuery.usernames = Arrays.copyOf(userQuery.usernames, userQuery.usernames.length + 1);
userQuery.usernames[userQuery.usernames.length - 1] = new StringPredicate(AssetQuery.Match.BEGIN, User.SERVICE_ACCOUNT_PREFIX).negate(true);
}
return ManagerIdentityProvider.getUsersFromDb(persistenceService, userQuery);
}
use of org.openremote.model.query.UserQuery in project openremote by openremote.
the class UserResourceImpl method query.
@Override
public User[] query(RequestParams requestParams, UserQuery query) {
AuthContext authContext = getAuthContext();
boolean isAdmin = authContext.hasResourceRole(ClientRole.READ_ADMIN.getValue(), authContext.getClientId());
boolean isRestricted = !isAdmin && authContext.hasResourceRole(ClientRole.READ_USERS.getValue(), authContext.getClientId());
if (!isAdmin && !isRestricted) {
throw new ForbiddenException("Insufficient permissions to read users");
}
if (query == null) {
query = new UserQuery();
}
if (isRestricted) {
if (query.select == null) {
query.select = new UserQuery.Select();
}
query.select.basic(true);
}
if (!authContext.isSuperUser()) {
// Force realm to match users
query.tenant(new TenantPredicate(authContext.getAuthenticatedRealm()));
// Hide system service accounts from non super users
if (query.select == null) {
query.select = new UserQuery.Select();
}
query.select.excludeSystemUsers = true;
}
try {
return identityService.getIdentityProvider().queryUsers(query);
} catch (ClientErrorException ex) {
throw new WebApplicationException(ex.getCause(), ex.getResponse().getStatus());
} catch (Exception ex) {
throw new WebApplicationException(ex);
}
}
use of org.openremote.model.query.UserQuery in project openremote by openremote.
the class PushNotificationHandler method getTargets.
@Override
public List<Notification.Target> getTargets(Notification.Source source, String sourceId, List<Notification.Target> targets, AbstractNotificationMessage message) {
// Check if message is going to a topic if so then filter consoles subscribed to that topic
PushNotificationMessage pushMessage = (PushNotificationMessage) message;
List<Notification.Target> mappedTargets = new ArrayList<>();
if (pushMessage.getTargetType() == TOPIC || pushMessage.getTargetType() == CONDITION) {
mappedTargets.add(new Notification.Target(Notification.TargetType.CUSTOM, pushMessage.getTargetType() + ": " + pushMessage.getTarget()));
return mappedTargets;
}
if (targets != null) {
targets.forEach(target -> {
Notification.TargetType targetType = target.getType();
String targetId = target.getId();
switch(targetType) {
case TENANT:
// Get all console assets with a push provider defined within the specified tenant
List<Asset<?>> consoleAssets = assetStorageService.findAll(new AssetQuery().select(new AssetQuery.Select().excludeAttributes()).tenant(new TenantPredicate(targetId)).types(ConsoleAsset.class).attributes(new AttributePredicate(ConsoleAsset.CONSOLE_PROVIDERS, null, false, new NameValuePredicate.Path(PushNotificationMessage.TYPE))));
// Get all user ids which have pushNotificationsDisabled set to false
String[] userIds = Arrays.stream(managerIdentityService.getIdentityProvider().queryUsers(new UserQuery().tenant(new TenantPredicate((targetId))))).filter(user -> Boolean.parseBoolean(user.getAttributes().getOrDefault(KEYCLOAK_USER_ATTRIBUTE_PUSH_NOTIFICATIONS_DISABLED, Collections.singletonList("false")).get(0))).map(User::getId).toArray(String[]::new);
String[] assetIds = assetStorageService.findUserAssetLinks(targetId, null, null).stream().filter(userAssetLink -> Arrays.stream(userIds).anyMatch(userId -> userId.equals(userAssetLink.getId().getUserId()))).map(userAssetLink -> userAssetLink.getId().getAssetId()).toArray(String[]::new);
// Remove consoleAssets which are linked to an User which has pushNotificationsDisabled set to false
consoleAssets = consoleAssets.stream().filter(consoleAsset -> Arrays.stream(assetIds).noneMatch(assetId -> assetId.equals(consoleAsset.getId()))).collect(Collectors.toList());
mappedTargets.addAll(consoleAssets.stream().map(asset -> new Notification.Target(Notification.TargetType.ASSET, asset.getId())).collect(Collectors.toList()));
break;
case USER:
Optional<User> user = Arrays.stream(managerIdentityService.getIdentityProvider().queryUsers(new UserQuery().ids(targetId))).findFirst();
if (user.isPresent() && !Boolean.parseBoolean(user.get().getAttributes().getOrDefault(KEYCLOAK_USER_ATTRIBUTE_PUSH_NOTIFICATIONS_DISABLED, Collections.singletonList("false")).get(0))) {
// Get all console assets linked to the specified user
String[] ids = assetStorageService.findUserAssetLinks(null, targetId, null).stream().map(userAssetLink -> userAssetLink.getId().getAssetId()).toArray(String[]::new);
if (ids.length > 0) {
mappedTargets.addAll(assetStorageService.findAll(new AssetQuery().select(new AssetQuery.Select().excludeAttributes()).ids(ids).types(ConsoleAsset.class).attributes(new AttributePredicate(ConsoleAsset.CONSOLE_PROVIDERS, null, false, new NameValuePredicate.Path(PushNotificationMessage.TYPE)))).stream().map(asset -> new Notification.Target(Notification.TargetType.ASSET, asset.getId())).collect(Collectors.toList()));
}
} else {
LOG.fine("No console assets linked to target user");
return;
}
break;
case ASSET:
// Find all console descendants of the specified asset
consoleAssets = assetStorageService.findAll(new AssetQuery().select(new AssetQuery.Select().excludeAttributes()).paths(new PathPredicate(targetId)).types(ConsoleAsset.class).attributes(new AttributePredicate(ConsoleAsset.CONSOLE_PROVIDERS, null, false, new NameValuePredicate.Path(PushNotificationMessage.TYPE))));
UserAssetLink[] userAssetLinks = consoleAssets.stream().map(consoleAsset -> assetStorageService.findUserAssetLinks(null, null, consoleAsset.getId())).flatMap(Collection::stream).toArray(UserAssetLink[]::new);
// Get all user ids which have pushNotificationsDisabled set to false
assetIds = Arrays.stream(userAssetLinks).filter(userAssetLink -> Arrays.stream(managerIdentityService.getIdentityProvider().queryUsers(new UserQuery().asset(new UserAssetPredicate(userAssetLink.getId().getAssetId())))).filter(user1 -> Boolean.parseBoolean(user1.getAttributes().getOrDefault(KEYCLOAK_USER_ATTRIBUTE_PUSH_NOTIFICATIONS_DISABLED, Collections.singletonList("false")).get(0))).map(User::getId).anyMatch(userId -> userId.equals(userAssetLink.getId().getUserId()))).map(userAssetLink -> userAssetLink.getId().getAssetId()).toArray(String[]::new);
// Remove consoleAssets which are linked to an User which has pushNotificationsDisabled set to false
consoleAssets = consoleAssets.stream().filter(consoleAsset -> Arrays.stream(assetIds).noneMatch(assetId -> assetId.equals(consoleAsset.getId()))).collect(Collectors.toList());
mappedTargets.addAll(consoleAssets.stream().map(asset -> new Notification.Target(Notification.TargetType.ASSET, asset.getId())).collect(Collectors.toList()));
break;
}
});
}
return mappedTargets;
}
use of org.openremote.model.query.UserQuery in project openremote by openremote.
the class EmailNotificationHandler method getTargets.
@Override
public List<Notification.Target> getTargets(Notification.Source source, String sourceId, List<Notification.Target> targets, AbstractNotificationMessage message) {
List<Notification.Target> mappedTargets = new ArrayList<>();
if (targets != null) {
targets.forEach(target -> {
Notification.TargetType targetType = target.getType();
String targetId = target.getId();
switch(targetType) {
case TENANT:
case USER:
// Find all users in this tenant or by id
User[] users = targetType == Notification.TargetType.TENANT ? managerIdentityService.getIdentityProvider().queryUsers(new UserQuery().tenant(new TenantPredicate(targetId))) : managerIdentityService.getIdentityProvider().queryUsers(new UserQuery().ids(targetId));
if (users.length == 0) {
if (targetType == Notification.TargetType.USER) {
LOG.info("User not found: " + targetId);
} else {
LOG.info("No users found in target realm: " + targetId);
}
return;
}
mappedTargets.addAll(Arrays.stream(users).filter(user -> !Boolean.parseBoolean(user.getAttributes().getOrDefault(KEYCLOAK_USER_ATTRIBUTE_EMAIL_NOTIFICATIONS_DISABLED, Collections.singletonList("false")).get(0))).map(user -> {
Notification.Target userAssetTarget = new Notification.Target(Notification.TargetType.USER, user.getId());
userAssetTarget.setData(new EmailNotificationMessage.Recipient(user.getFullName(), user.getEmail()));
return userAssetTarget;
}).collect(Collectors.toList()));
break;
case CUSTOM:
// Nothing to do here
mappedTargets.add(new Notification.Target(targetType, targetId));
break;
case ASSET:
// Find descendant assets with email attribute
List<Asset<?>> assets = assetStorageService.findAll(new AssetQuery().select(new AssetQuery.Select().attributes(Asset.EMAIL.getName())).paths(new PathPredicate(targetId)).attributes(new AttributePredicate(new StringPredicate(Asset.EMAIL.getName()), new ValueEmptyPredicate().negate(true))));
if (assets.isEmpty()) {
LOG.fine("No assets with email attribute descendants of target asset");
return;
}
mappedTargets.addAll(assets.stream().map(asset -> {
Notification.Target assetTarget = new Notification.Target(Notification.TargetType.ASSET, asset.getId());
assetTarget.setData(new EmailNotificationMessage.Recipient(asset.getName(), asset.getEmail().orElse(null)));
return assetTarget;
}).collect(Collectors.toList()));
break;
}
});
}
EmailNotificationMessage email = (EmailNotificationMessage) message;
// Map to/cc/bcc into a custom target for traceability in sent notifications
List<String> addresses = new ArrayList<>();
if (email.getTo() != null) {
addresses.addAll(email.getTo().stream().map(EmailNotificationMessage.Recipient::getAddress).map(address -> "to:" + address).collect(Collectors.toList()));
email.setTo((List<EmailNotificationMessage.Recipient>) null);
}
if (email.getCc() != null) {
addresses.addAll(email.getCc().stream().map(EmailNotificationMessage.Recipient::getAddress).map(address -> "cc:" + address).collect(Collectors.toList()));
email.setCc((List<EmailNotificationMessage.Recipient>) null);
}
if (email.getBcc() != null) {
addresses.addAll(email.getBcc().stream().map(EmailNotificationMessage.Recipient::getAddress).map(address -> "bcc:" + address).collect(Collectors.toList()));
email.setBcc((List<EmailNotificationMessage.Recipient>) null);
}
if (!addresses.isEmpty()) {
mappedTargets.add(new Notification.Target(Notification.TargetType.CUSTOM, String.join(";", addresses)));
}
return mappedTargets;
}
Aggregations