Search in sources :

Example 41 with AccountState

use of com.google.gerrit.server.account.AccountState in project gerrit by GerritCodeReview.

the class GerritPublicKeyChecker method checkIdsForArbitraryUser.

private CheckResult checkIdsForArbitraryUser(PGPPublicKey key) throws PGPException {
    List<AccountState> accountStates = accountQueryProvider.get().byExternalId(toExtIdKey(key));
    if (accountStates.isEmpty()) {
        return CheckResult.bad("Key is not associated with any users");
    }
    if (accountStates.size() > 1) {
        return CheckResult.bad("Key is associated with multiple users");
    }
    IdentifiedUser user = userFactory.create(accountStates.get(0));
    Set<String> allowedUserIds = getAllowedUserIds(user);
    if (allowedUserIds.isEmpty()) {
        return CheckResult.bad("No identities found for user");
    }
    if (hasAllowedUserId(key, allowedUserIds)) {
        return CheckResult.trusted();
    }
    return CheckResult.bad("Key does not contain any valid certifications for user's identities");
}
Also used : AccountState(com.google.gerrit.server.account.AccountState) PublicKeyStore.keyIdToString(com.google.gerrit.gpg.PublicKeyStore.keyIdToString) IdentifiedUser(com.google.gerrit.server.IdentifiedUser)

Example 42 with AccountState

use of com.google.gerrit.server.account.AccountState in project gerrit by GerritCodeReview.

the class OutgoingEmail method sendImpl.

private void sendImpl() throws EmailException {
    if (!args.emailSender.isEnabled()) {
        // Server has explicitly disabled email sending.
        // 
        logger.atFine().log("Not sending '%s': Email sending is disabled by server config", messageClass);
        return;
    }
    if (!notify.shouldNotify()) {
        logger.atFine().log("Not sending '%s': Notify handling is NONE", messageClass);
        return;
    }
    init();
    if (messageId == null) {
        throw new IllegalStateException("All emails must have a messageId");
    }
    format();
    appendText(textTemplate("Footer"));
    if (useHtml()) {
        appendHtml(soyHtmlTemplate("FooterHtml"));
    }
    Set<Address> smtpRcptToPlaintextOnly = new HashSet<>();
    if (shouldSendMessage()) {
        if (fromId != null) {
            Optional<AccountState> fromUser = args.accountCache.get(fromId);
            if (fromUser.isPresent()) {
                GeneralPreferencesInfo senderPrefs = fromUser.get().generalPreferences();
                CurrentUser user = args.currentUserProvider.get();
                boolean isImpersonating = user.isIdentifiedUser() && user.isImpersonating();
                if (isImpersonating && user.getAccountId() != fromId) {
                    // set up correctly.
                    throw new EmailException(String.format("User %s is sending email from %s, while acting on behalf of %s", user.asIdentifiedUser().getRealUser().getAccountId(), fromId, user.getAccountId()));
                }
                if (senderPrefs != null && senderPrefs.getEmailStrategy() == CC_ON_OWN_COMMENTS) {
                    // Include the sender in email if they enabled email notifications on their own
                    // comments.
                    // 
                    logger.atFine().log("CC email sender %s because the email strategy of this user is %s", fromUser.get().account().id(), CC_ON_OWN_COMMENTS);
                    add(RecipientType.CC, fromId);
                } else if (isImpersonating) {
                    // If we are impersonating a user, make sure they receive a CC of
                    // this message regardless of email strategy, unless email notifications are explicitly
                    // disabled for this user. This way they can always review and audit what we sent
                    // on their behalf to others.
                    logger.atFine().log("CC email sender %s because the email is sent on behalf of and email notifications" + " are enabled for this user.", fromUser.get().account().id());
                    add(RecipientType.CC, fromId);
                } else if (!notify.accounts().containsValue(fromId) && rcptTo.remove(fromId)) {
                    // If they don't want a copy, but we queued one up anyway,
                    // drop them from the recipient lists, but only if the user is not being impersonated.
                    // 
                    logger.atFine().log("Not CCing email sender %s because the email strategy of this user is not %s but" + " %s", fromUser.get().account().id(), CC_ON_OWN_COMMENTS, senderPrefs != null ? senderPrefs.getEmailStrategy() : null);
                    removeUser(fromUser.get().account());
                }
            }
        }
        // In addition, check if users only want to receive plaintext email.
        for (Account.Id id : rcptTo) {
            Optional<AccountState> thisUser = args.accountCache.get(id);
            if (thisUser.isPresent()) {
                Account thisUserAccount = thisUser.get().account();
                GeneralPreferencesInfo prefs = thisUser.get().generalPreferences();
                if (prefs == null || prefs.getEmailStrategy() == DISABLED) {
                    logger.atFine().log("Not emailing account %s because user has set email strategy to %s", id, DISABLED);
                    removeUser(thisUserAccount);
                } else if (useHtml() && prefs.getEmailFormat() == EmailFormat.PLAINTEXT) {
                    logger.atFine().log("Removing account %s from HTML email because user prefers plain text emails", id);
                    removeUser(thisUserAccount);
                    smtpRcptToPlaintextOnly.add(Address.create(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
                }
            }
            if (smtpRcptTo.isEmpty() && smtpRcptToPlaintextOnly.isEmpty()) {
                logger.atFine().log("Not sending '%s': No SMTP recipients", messageClass);
                return;
            }
        }
        // inbound email replies.
        if (!headers.containsKey(FieldName.REPLY_TO)) {
            StringJoiner j = new StringJoiner(", ");
            if (fromId != null) {
                Address address = toAddress(fromId);
                if (address != null) {
                    j.add(address.email());
                }
            }
            // For users who prefer plaintext, this comes at the cost of not being
            // listed in the multipart To and Cc headers. We work around this by adding
            // all users to the Reply-To address in both the plaintext and multipart
            // email. We should exclude any BCC addresses from reply-to, because they should be
            // invisible to other recipients.
            Sets.difference(Sets.union(smtpRcptTo, smtpRcptToPlaintextOnly), smtpBccRcptTo).stream().forEach(a -> j.add(a.email()));
            setHeader(FieldName.REPLY_TO, j.toString());
        }
        String textPart = textBody.toString();
        OutgoingEmailValidationListener.Args va = new OutgoingEmailValidationListener.Args();
        va.messageClass = messageClass;
        va.smtpFromAddress = smtpFromAddress;
        va.smtpRcptTo = smtpRcptTo;
        va.headers = headers;
        va.body = textPart;
        if (useHtml()) {
            va.htmlBody = htmlBody.toString();
        } else {
            va.htmlBody = null;
        }
        Set<Address> intersection = Sets.intersection(va.smtpRcptTo, smtpRcptToPlaintextOnly);
        if (!intersection.isEmpty()) {
            logger.atSevere().log("Email '%s' will be sent twice to %s", messageClass, intersection);
        }
        if (!va.smtpRcptTo.isEmpty()) {
            // Send multipart message
            addMessageId(va, "-HTML");
            if (!validateEmail(va))
                return;
            logger.atFine().log("Sending multipart '%s' from %s to %s", messageClass, va.smtpFromAddress, va.smtpRcptTo);
            args.emailSender.send(va.smtpFromAddress, va.smtpRcptTo, va.headers, va.body, va.htmlBody);
        }
        if (!smtpRcptToPlaintextOnly.isEmpty()) {
            addMessageId(va, "-PLAIN");
            // Send plaintext message
            Map<String, EmailHeader> shallowCopy = new HashMap<>();
            shallowCopy.putAll(headers);
            // Remove To and Cc
            shallowCopy.remove(FieldName.TO);
            shallowCopy.remove(FieldName.CC);
            for (Address a : smtpRcptToPlaintextOnly) {
                // Add new To
                EmailHeader.AddressList to = new EmailHeader.AddressList();
                to.add(a);
                shallowCopy.put(FieldName.TO, to);
            }
            if (!validateEmail(va))
                return;
            logger.atFine().log("Sending plaintext '%s' from %s to %s", messageClass, va.smtpFromAddress, smtpRcptToPlaintextOnly);
            args.emailSender.send(va.smtpFromAddress, smtpRcptToPlaintextOnly, shallowCopy, va.body);
        }
    }
}
Also used : Account(com.google.gerrit.entities.Account) Address(com.google.gerrit.entities.Address) CurrentUser(com.google.gerrit.server.CurrentUser) EmailHeader(com.google.gerrit.entities.EmailHeader) StringEmailHeader(com.google.gerrit.entities.EmailHeader.StringEmailHeader) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) AccountState(com.google.gerrit.server.account.AccountState) OutgoingEmailValidationListener(com.google.gerrit.server.validators.OutgoingEmailValidationListener) AddressList(com.google.gerrit.entities.EmailHeader.AddressList) EmailException(com.google.gerrit.exceptions.EmailException) GeneralPreferencesInfo(com.google.gerrit.extensions.client.GeneralPreferencesInfo) AddressList(com.google.gerrit.entities.EmailHeader.AddressList) StringJoiner(java.util.StringJoiner) HashSet(java.util.HashSet)

Example 43 with AccountState

use of com.google.gerrit.server.account.AccountState in project gerrit by GerritCodeReview.

the class OutgoingEmail method getNameEmailFor.

/**
 * Gets the human readable name and email for an account; if neither are available, returns the
 * Anonymous Coward name.
 *
 * @param accountId user to fetch.
 * @return name/email of account, or Anonymous Coward if unset.
 */
protected String getNameEmailFor(@Nullable Account.Id accountId) {
    if (accountId == null) {
        PersonIdent gerritIdent = args.gerritPersonIdent.get();
        return gerritIdent.getName() + " <" + gerritIdent.getEmailAddress() + ">";
    }
    Optional<Account> account = args.accountCache.get(accountId).map(AccountState::account);
    if (account.isPresent()) {
        String name = account.get().fullName();
        String email = account.get().preferredEmail();
        if (name != null && email != null) {
            return name + " <" + email + ">";
        } else if (name != null) {
            return name;
        } else if (email != null) {
            return email;
        }
    }
    return args.anonymousCowardName + " #" + accountId;
}
Also used : Account(com.google.gerrit.entities.Account) PersonIdent(org.eclipse.jgit.lib.PersonIdent) AccountState(com.google.gerrit.server.account.AccountState)

Example 44 with AccountState

use of com.google.gerrit.server.account.AccountState in project gerrit by GerritCodeReview.

the class MailProcessor method processImpl.

private void processImpl(BatchUpdate.Factory buf, MailMessage message) throws UpdateException, RestApiException, IOException {
    for (Extension<MailFilter> filter : mailFilters) {
        if (!filter.getProvider().get().shouldProcessMessage(message)) {
            logger.atWarning().log("Message %s filtered by plugin %s %s. Will delete message.", message.id(), filter.getPluginName(), filter.getExportName());
            return;
        }
    }
    MailMetadata metadata = MailHeaderParser.parse(message);
    if (!metadata.hasRequiredFields()) {
        logger.atSevere().log("Message %s is missing required metadata, have %s. Will delete message.", message.id(), metadata);
        sendRejectionEmail(message, InboundEmailError.PARSING_ERROR);
        return;
    }
    Set<Account.Id> accountIds = emails.getAccountFor(metadata.author);
    if (accountIds.size() != 1) {
        logger.atSevere().log("Address %s could not be matched to a unique account. It was matched to %s." + " Will delete message.", metadata.author, accountIds);
        // We don't want to send an email if no accounts are linked to it.
        if (accountIds.size() > 1) {
            sendRejectionEmail(message, InboundEmailError.UNKNOWN_ACCOUNT);
        }
        return;
    }
    Account.Id accountId = accountIds.iterator().next();
    Optional<AccountState> accountState = accountCache.get(accountId);
    if (!accountState.isPresent()) {
        logger.atWarning().log("Mail: Account %s doesn't exist. Will delete message.", accountId);
        return;
    }
    if (!accountState.get().account().isActive()) {
        logger.atWarning().log("Mail: Account %s is inactive. Will delete message.", accountId);
        sendRejectionEmail(message, InboundEmailError.INACTIVE_ACCOUNT);
        return;
    }
    persistComments(buf, message, metadata, accountId);
}
Also used : MailFilter(com.google.gerrit.server.mail.MailFilter) Account(com.google.gerrit.entities.Account) MailMetadata(com.google.gerrit.mail.MailMetadata) AccountState(com.google.gerrit.server.account.AccountState)

Example 45 with AccountState

use of com.google.gerrit.server.account.AccountState in project gerrit by GerritCodeReview.

the class PutAgreement method apply.

@Override
public Response<String> apply(AccountResource resource, AgreementInput input) throws IOException, RestApiException, ConfigInvalidException {
    if (!agreementsEnabled) {
        throw new MethodNotAllowedException("contributor agreements disabled");
    }
    if (!self.get().hasSameAccountId(resource.getUser())) {
        throw new AuthException("not allowed to enter contributor agreement");
    }
    String agreementName = Strings.nullToEmpty(input.name);
    ContributorAgreement ca = projectCache.getAllProjects().getConfig().getContributorAgreements().get(agreementName);
    if (ca == null) {
        throw new UnprocessableEntityException("contributor agreement not found");
    }
    if (ca.getAutoVerify() == null) {
        throw new BadRequestException("cannot enter a non-autoVerify agreement");
    }
    AccountGroup.UUID uuid = ca.getAutoVerify().getUUID();
    if (uuid == null) {
        throw new ResourceConflictException("autoverify group uuid not found");
    }
    AccountState accountState = self.get().state();
    try {
        addMembers.addMembers(uuid, ImmutableSet.of(accountState.account().id()));
    } catch (NoSuchGroupException e) {
        throw new ResourceConflictException("autoverify group not found", e);
    }
    agreementSignup.fire(accountState, agreementName);
    return Response.ok(agreementName);
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) MethodNotAllowedException(com.google.gerrit.extensions.restapi.MethodNotAllowedException) AccountGroup(com.google.gerrit.entities.AccountGroup) ContributorAgreement(com.google.gerrit.entities.ContributorAgreement) AuthException(com.google.gerrit.extensions.restapi.AuthException) BadRequestException(com.google.gerrit.extensions.restapi.BadRequestException) AccountState(com.google.gerrit.server.account.AccountState) NoSuchGroupException(com.google.gerrit.exceptions.NoSuchGroupException)

Aggregations

AccountState (com.google.gerrit.server.account.AccountState)63 Account (com.google.gerrit.entities.Account)37 ExternalId (com.google.gerrit.server.account.externalids.ExternalId)18 IOException (java.io.IOException)17 Test (org.junit.Test)16 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)15 Inject (com.google.inject.Inject)15 ConfigInvalidException (org.eclipse.jgit.errors.ConfigInvalidException)14 AuthException (com.google.gerrit.extensions.restapi.AuthException)12 ArrayList (java.util.ArrayList)12 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)11 HashSet (java.util.HashSet)11 List (java.util.List)11 ImmutableSet (com.google.common.collect.ImmutableSet)10 BadRequestException (com.google.gerrit.extensions.restapi.BadRequestException)10 ResourceNotFoundException (com.google.gerrit.extensions.restapi.ResourceNotFoundException)10 AccountsUpdate (com.google.gerrit.server.account.AccountsUpdate)10 TestAccount (com.google.gerrit.acceptance.TestAccount)9 Nullable (com.google.gerrit.common.Nullable)9 StorageException (com.google.gerrit.exceptions.StorageException)9