Search in sources :

Example 61 with CurrentUser

use of com.google.gerrit.server.CurrentUser in project gerrit by GerritCodeReview.

the class ConfirmEmail method apply.

@Override
public Response<?> apply(ConfigResource rsrc, Input input) throws AuthException, UnprocessableEntityException, IOException, ConfigInvalidException {
    CurrentUser user = self.get();
    if (!user.isIdentifiedUser()) {
        throw new AuthException("Authentication required");
    }
    if (input == null) {
        input = new Input();
    }
    if (input.token == null) {
        throw new UnprocessableEntityException("missing token");
    }
    try {
        EmailTokenVerifier.ParsedToken token = emailTokenVerifier.decode(input.token);
        Account.Id accId = user.getAccountId();
        if (accId.equals(token.getAccountId())) {
            accountManager.link(accId, token.toAuthRequest());
            return Response.none();
        }
        throw new UnprocessableEntityException("invalid token");
    } catch (EmailTokenVerifier.InvalidTokenException e) {
        throw new UnprocessableEntityException("invalid token", e);
    } catch (AccountException e) {
        throw new UnprocessableEntityException(e.getMessage());
    }
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) Account(com.google.gerrit.entities.Account) Input(com.google.gerrit.server.restapi.config.ConfirmEmail.Input) DefaultInput(com.google.gerrit.extensions.restapi.DefaultInput) EmailTokenVerifier(com.google.gerrit.server.mail.EmailTokenVerifier) CurrentUser(com.google.gerrit.server.CurrentUser) AccountException(com.google.gerrit.server.account.AccountException) AuthException(com.google.gerrit.extensions.restapi.AuthException)

Example 62 with CurrentUser

use of com.google.gerrit.server.CurrentUser in project gerrit by GerritCodeReview.

the class Receive method runImpl.

@Override
protected void runImpl() throws IOException, Failure {
    CurrentUser currentUser = session.getUser();
    try {
        permissionBackend.user(currentUser).project(project.getNameKey()).check(ProjectPermission.RUN_RECEIVE_PACK);
    } catch (AuthException e) {
        throw new Failure(1, "fatal: receive-pack not permitted on this server", e);
    } catch (PermissionBackendException e) {
        throw new Failure(1, "fatal: unable to check permissions " + e);
    }
    AsyncReceiveCommits arc = factory.create(projectState, currentUser.asIdentifiedUser(), repo, null);
    try {
        Capable r = arc.canUpload();
        if (r != Capable.OK) {
            throw die(r.getMessage());
        }
    } catch (PermissionBackendException e) {
        throw die(e.getMessage());
    }
    ReceivePack rp = arc.getReceivePack();
    try {
        rp.receive(in, out, err);
        session.setPeerAgent(rp.getPeerUserAgent());
    } catch (UnpackException badStream) {
        // we want to present this error to the user
        if (badStream.getCause() instanceof TooLargeObjectInPackException) {
            StringBuilder msg = new StringBuilder();
            msg.append("Receive error on project \"").append(projectState.getName()).append("\"");
            msg.append(" (user ");
            msg.append(currentUser.getUserName().orElse(null));
            msg.append(" account ");
            msg.append(currentUser.getAccountId());
            msg.append("): ");
            msg.append(badStream.getCause().getMessage());
            logger.atInfo().log(msg.toString());
            throw new UnloggedFailure(128, "error: " + badStream.getCause().getMessage());
        }
        StringBuilder msg = new StringBuilder();
        msg.append("Unpack error on project \"").append(projectState.getName()).append("\":\n");
        msg.append("  AdvertiseRefsHook: ").append(rp.getAdvertiseRefsHook());
        if (rp.getAdvertiseRefsHook() == AdvertiseRefsHook.DEFAULT) {
            msg.append("DEFAULT");
        } else {
            msg.append(rp.getAdvertiseRefsHook().getClass());
        }
        msg.append("\n");
        IOException detail = new IOException(msg.toString(), badStream);
        throw new Failure(128, "fatal: Unpack error, check server log", detail);
    }
}
Also used : TooLargeObjectInPackException(org.eclipse.jgit.errors.TooLargeObjectInPackException) AsyncReceiveCommits(com.google.gerrit.server.git.receive.AsyncReceiveCommits) Capable(com.google.gerrit.common.data.Capable) UnpackException(org.eclipse.jgit.errors.UnpackException) CurrentUser(com.google.gerrit.server.CurrentUser) AuthException(com.google.gerrit.extensions.restapi.AuthException) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) ReceivePack(org.eclipse.jgit.transport.ReceivePack) IOException(java.io.IOException)

Example 63 with CurrentUser

use of com.google.gerrit.server.CurrentUser 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 64 with CurrentUser

use of com.google.gerrit.server.CurrentUser in project gerrit by GerritCodeReview.

the class ProjectWatch method add.

private void add(Watchers matching, Project.NameKey projectName, NotifyConfig nc) throws QueryParseException {
    logger.atFine().log("Checking watchers for notify config %s from project %s", nc, projectName);
    for (GroupReference groupRef : nc.getGroups()) {
        CurrentUser user = new GroupBackedUser(ImmutableSet.of(groupRef.getUUID()));
        if (filterMatch(user, nc.getFilter())) {
            deliverToMembers(matching.list(nc.getHeader()), groupRef.getUUID());
            logger.atFine().log("Added watchers for group %s", groupRef);
        } else {
            logger.atFine().log("The filter did not match for group %s; skip notification", groupRef);
        }
    }
    if (!nc.getAddresses().isEmpty()) {
        if (filterMatch(null, nc.getFilter())) {
            matching.list(nc.getHeader()).emails.addAll(nc.getAddresses());
            logger.atFine().log("Added watchers for these addresses: %s", nc.getAddresses());
        } else {
            logger.atFine().log("The filter did not match; skip notification for these addresses: %s", nc.getAddresses());
        }
    }
}
Also used : CurrentUser(com.google.gerrit.server.CurrentUser) GroupReference(com.google.gerrit.entities.GroupReference) GroupBackedUser(com.google.gerrit.server.query.change.GroupBackedUser)

Example 65 with CurrentUser

use of com.google.gerrit.server.CurrentUser in project gerrit by GerritCodeReview.

the class DeleteDraftComments method apply.

@Override
public Response<ImmutableList<DeletedDraftCommentInfo>> apply(AccountResource rsrc, DeleteDraftCommentsInput input) throws RestApiException, UpdateException {
    CurrentUser user = userProvider.get();
    if (!user.isIdentifiedUser()) {
        throw new AuthException("Authentication required");
    }
    if (!rsrc.getUser().hasSameAccountId(user)) {
        // hasSameAccountId check.)
        throw new AuthException("Cannot delete drafts of other user");
    }
    HumanCommentFormatter humanCommentFormatter = commentJsonProvider.get().newHumanCommentFormatter();
    Account.Id accountId = rsrc.getUser().getAccountId();
    Instant now = TimeUtil.now();
    Map<Project.NameKey, BatchUpdate> updates = new LinkedHashMap<>();
    List<Op> ops = new ArrayList<>();
    for (ChangeData cd : queryProvider.get().enforceVisibility(true).query(predicate(accountId, input))) {
        BatchUpdate update = updates.computeIfAbsent(cd.project(), p -> batchUpdateFactory.create(p, rsrc.getUser(), now));
        Op op = new Op(humanCommentFormatter, accountId);
        update.addOp(cd.getId(), op);
        ops.add(op);
    }
    // Currently there's no way to let some updates succeed even if others fail. Even if there were,
    // all updates from this operation only happen in All-Users and thus are fully atomic, so
    // allowing partial failure would have little value.
    BatchUpdate.execute(updates.values(), ImmutableList.of(), false);
    return Response.ok(ops.stream().map(Op::getResult).filter(Objects::nonNull).collect(toImmutableList()));
}
Also used : Account(com.google.gerrit.entities.Account) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) CurrentUser(com.google.gerrit.server.CurrentUser) Instant(java.time.Instant) ArrayList(java.util.ArrayList) AuthException(com.google.gerrit.extensions.restapi.AuthException) ChangeData(com.google.gerrit.server.query.change.ChangeData) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) LinkedHashMap(java.util.LinkedHashMap) Objects(java.util.Objects) HumanCommentFormatter(com.google.gerrit.server.restapi.change.CommentJson.HumanCommentFormatter)

Aggregations

CurrentUser (com.google.gerrit.server.CurrentUser)73 AuthException (com.google.gerrit.extensions.restapi.AuthException)21 Account (com.google.gerrit.reviewdb.client.Account)11 Account (com.google.gerrit.entities.Account)10 PermissionBackend (com.google.gerrit.server.permissions.PermissionBackend)10 PermissionBackendException (com.google.gerrit.server.permissions.PermissionBackendException)10 ChangeData (com.google.gerrit.server.query.change.ChangeData)10 Change (com.google.gerrit.entities.Change)9 UnprocessableEntityException (com.google.gerrit.extensions.restapi.UnprocessableEntityException)9 IdentifiedUser (com.google.gerrit.server.IdentifiedUser)9 IOException (java.io.IOException)9 ResourceNotFoundException (com.google.gerrit.extensions.restapi.ResourceNotFoundException)8 ChangeNotes (com.google.gerrit.server.notedb.ChangeNotes)8 BatchUpdate (com.google.gerrit.server.update.BatchUpdate)8 Provider (com.google.inject.Provider)8 HashMap (java.util.HashMap)8 ArrayList (java.util.ArrayList)6 Map (java.util.Map)6 Test (org.junit.Test)6 PatchSet (com.google.gerrit.entities.PatchSet)5