Search in sources :

Example 1 with UserQuery

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]);
}
Also used : IdentityProvider(org.openremote.container.security.IdentityProvider) AssetStorageService(org.openremote.manager.asset.AssetStorageService) org.openremote.model.security(org.openremote.model.security) IntStream(java.util.stream.IntStream) java.util(java.util) AssetStorageService.buildMatchFilter(org.openremote.manager.asset.AssetStorageService.buildMatchFilter) AuthContext(org.openremote.container.security.AuthContext) MASTER_REALM(org.openremote.model.Constants.MASTER_REALM) TypedQuery(javax.persistence.TypedQuery) Collectors(java.util.stream.Collectors) TenantFilter(org.openremote.model.event.shared.TenantFilter) StringPredicate(org.openremote.model.query.filter.StringPredicate) UserQuery(org.openremote.model.query.UserQuery) PersistenceService(org.openremote.container.persistence.PersistenceService) TextUtil(org.openremote.model.util.TextUtil) StringPredicate(org.openremote.model.query.filter.StringPredicate) UserQuery(org.openremote.model.query.UserQuery)

Example 2 with UserQuery

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);
}
Also used : StringPredicate(org.openremote.model.query.filter.StringPredicate) UserQuery(org.openremote.model.query.UserQuery)

Example 3 with 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);
    }
}
Also used : UserQuery(org.openremote.model.query.UserQuery) AuthContext(org.openremote.container.security.AuthContext) TenantPredicate(org.openremote.model.query.filter.TenantPredicate)

Example 4 with UserQuery

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;
}
Also used : AssetStorageService(org.openremote.manager.asset.AssetStorageService) GatewayService.isNotForGateway(org.openremote.manager.gateway.GatewayService.isNotForGateway) UserAssetLink(org.openremote.model.asset.UserAssetLink) java.util(java.util) com.google.firebase.messaging(com.google.firebase.messaging) AbstractNotificationMessage(org.openremote.model.notification.AbstractNotificationMessage) FirebaseOptions(com.google.firebase.FirebaseOptions) ValueUtil(org.openremote.model.util.ValueUtil) Level(java.util.logging.Level) Notification(org.openremote.model.notification.Notification) UserQuery(org.openremote.model.query.UserQuery) PersistenceService(org.openremote.container.persistence.PersistenceService) ConsoleProvider(org.openremote.model.console.ConsoleProvider) org.openremote.model.query.filter(org.openremote.model.query.filter) StreamSupport(java.util.stream.StreamSupport) TextUtil(org.openremote.model.util.TextUtil) TypeReference(com.fasterxml.jackson.core.type.TypeReference) NotificationSendResult(org.openremote.model.notification.NotificationSendResult) PersistenceEvent(org.openremote.model.PersistenceEvent) MessageBrokerService(org.openremote.container.message.MessageBrokerService) User(org.openremote.model.security.User) TargetType(org.openremote.model.notification.PushNotificationMessage.TargetType) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) Asset(org.openremote.model.asset.Asset) Files(java.nio.file.Files) GoogleCredentials(com.google.auth.oauth2.GoogleCredentials) KEYCLOAK_USER_ATTRIBUTE_PUSH_NOTIFICATIONS_DISABLED(org.openremote.manager.security.ManagerKeycloakIdentityProvider.KEYCLOAK_USER_ATTRIBUTE_PUSH_NOTIFICATIONS_DISABLED) AssetQuery(org.openremote.model.query.AssetQuery) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) ContainerService(org.openremote.model.ContainerService) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) Container(org.openremote.model.Container) PushNotificationMessage(org.openremote.model.notification.PushNotificationMessage) RouteBuilder(org.apache.camel.builder.RouteBuilder) ConsoleAsset(org.openremote.model.asset.impl.ConsoleAsset) Paths(java.nio.file.Paths) GatewayService(org.openremote.manager.gateway.GatewayService) FirebaseApp(com.google.firebase.FirebaseApp) InputStream(java.io.InputStream) GlobalLock.withLock(org.openremote.container.concurrent.GlobalLock.withLock) User(org.openremote.model.security.User) Notification(org.openremote.model.notification.Notification) UserAssetLink(org.openremote.model.asset.UserAssetLink) Asset(org.openremote.model.asset.Asset) ConsoleAsset(org.openremote.model.asset.impl.ConsoleAsset) ConsoleAsset(org.openremote.model.asset.impl.ConsoleAsset) AssetQuery(org.openremote.model.query.AssetQuery) UserQuery(org.openremote.model.query.UserQuery) PushNotificationMessage(org.openremote.model.notification.PushNotificationMessage)

Example 5 with UserQuery

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;
}
Also used : AssetStorageService(org.openremote.manager.asset.AssetStorageService) Arrays(java.util.Arrays) AbstractNotificationMessage(org.openremote.model.notification.AbstractNotificationMessage) KEYCLOAK_USER_ATTRIBUTE_EMAIL_NOTIFICATIONS_DISABLED(org.openremote.manager.security.ManagerKeycloakIdentityProvider.KEYCLOAK_USER_ATTRIBUTE_EMAIL_NOTIFICATIONS_DISABLED) EmailPopulatingBuilder(org.simplejavamail.email.EmailPopulatingBuilder) TransportStrategy(org.simplejavamail.mailer.config.TransportStrategy) MapAccess.getInteger(org.openremote.container.util.MapAccess.getInteger) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) Notification(org.openremote.model.notification.Notification) UserQuery(org.openremote.model.query.UserQuery) Recipient(org.simplejavamail.email.Recipient) org.openremote.model.query.filter(org.openremote.model.query.filter) EmailNotificationMessage(org.openremote.model.notification.EmailNotificationMessage) MapAccess.getBoolean(org.openremote.container.util.MapAccess.getBoolean) TextUtil(org.openremote.model.util.TextUtil) NotificationSendResult(org.openremote.model.notification.NotificationSendResult) User(org.openremote.model.security.User) ManagerIdentityService(org.openremote.manager.security.ManagerIdentityService) Asset(org.openremote.model.asset.Asset) MailerBuilder(org.simplejavamail.mailer.MailerBuilder) AssetQuery(org.openremote.model.query.AssetQuery) Mailer(org.simplejavamail.mailer.Mailer) ContainerService(org.openremote.model.ContainerService) Logger(java.util.logging.Logger) Constants(org.openremote.model.Constants) Collectors(java.util.stream.Collectors) Container(org.openremote.model.Container) List(java.util.List) EmailBuilder(org.simplejavamail.email.EmailBuilder) Email(org.simplejavamail.email.Email) Collections(java.util.Collections) EmailNotificationMessage(org.openremote.model.notification.EmailNotificationMessage) User(org.openremote.model.security.User) AssetQuery(org.openremote.model.query.AssetQuery) ArrayList(java.util.ArrayList) Recipient(org.simplejavamail.email.Recipient) Notification(org.openremote.model.notification.Notification) UserQuery(org.openremote.model.query.UserQuery) Asset(org.openremote.model.asset.Asset)

Aggregations

UserQuery (org.openremote.model.query.UserQuery)5 Collectors (java.util.stream.Collectors)3 AssetStorageService (org.openremote.manager.asset.AssetStorageService)3 TextUtil (org.openremote.model.util.TextUtil)3 java.util (java.util)2 Level (java.util.logging.Level)2 Logger (java.util.logging.Logger)2 PersistenceService (org.openremote.container.persistence.PersistenceService)2 AuthContext (org.openremote.container.security.AuthContext)2 ManagerIdentityService (org.openremote.manager.security.ManagerIdentityService)2 Container (org.openremote.model.Container)2 ContainerService (org.openremote.model.ContainerService)2 Asset (org.openremote.model.asset.Asset)2 AbstractNotificationMessage (org.openremote.model.notification.AbstractNotificationMessage)2 Notification (org.openremote.model.notification.Notification)2 NotificationSendResult (org.openremote.model.notification.NotificationSendResult)2 AssetQuery (org.openremote.model.query.AssetQuery)2 org.openremote.model.query.filter (org.openremote.model.query.filter)2 StringPredicate (org.openremote.model.query.filter.StringPredicate)2 User (org.openremote.model.security.User)2