private List<List<ChangeInfo>> query() throws OrmException, QueryParseException { if (imp.isDisabled()) { throw new QueryParseException("query disabled"); } if (queries == null || queries.isEmpty()) { queries = Collections.singletonList("status:open"); } else if (queries.size() > 10) { // Hard-code a default maximum number of queries to prevent // users from submitting too much to the server in a single call. throw new QueryParseException("limit of 10 queries"); } IdentifiedUser self = null; try { if (user.get().isIdentifiedUser()) { self = (IdentifiedUser) user.get(); self.asyncStarredChanges(); } return query0(); } finally { if (self != null) { self.abortStarredChanges(); } } }
private void postAdd(Change change, PostResult result) throws OrmException, EmailException { if (result.reviewers.isEmpty()) { return; } // Execute hook for added reviewers // PatchSet patchSet = db.get().patchSets().get(change.currentPatchSetId()); for (AccountInfo info : result.reviewers) { Account account = accountCache.get(info._id).getAccount(); hooks.doReviewerAddedHook(change, account, patchSet, db.get()); } // Email the reviewers // // The user knows they added themselves, don't bother emailing them. List<Account.Id> added = Lists.newArrayListWithCapacity(result.reviewers.size()); for (AccountInfo info : result.reviewers) { if (!info._id.equals(currentUser.getAccountId())) { added.add(info._id); } } if (!added.isEmpty()) { AddReviewerSender cm; cm = addReviewerSenderFactory.create(change); cm.setFrom(currentUser.getAccountId()); cm.addReviewers(added); cm.send(); } }
private void addReviewers(ChangeResource rsrc, PostResult result, Set<IdentifiedUser> reviewers) throws OrmException, EmailException { if (reviewers.isEmpty()) { result.reviewers = ImmutableList.of(); return; } PatchSet.Id psid = rsrc.getChange().currentPatchSetId(); Set<Account.Id> existing = Sets.newHashSet(); for (PatchSetApproval psa : db.get().patchSetApprovals().byPatchSet(psid)) { existing.add(psa.getAccountId()); } result.reviewers = Lists.newArrayListWithCapacity(reviewers.size()); List<PatchSetApproval> toInsert = Lists.newArrayListWithCapacity(reviewers.size()); for (IdentifiedUser user : reviewers) { Account.Id id = user.getAccountId(); if (existing.contains(id)) { continue; } ChangeControl control = rsrc.getControl().forUser(user); PatchSetApproval psa = dummyApproval(control, psid, id); result.reviewers.add(json.format(new ReviewerInfo(id), control, ImmutableList.of(psa))); toInsert.add(psa); } db.get().patchSetApprovals().insert(toInsert); accountLoaderFactory.create(true).fill(result.reviewers); postAdd(rsrc.getChange(), result); }
public void setFrom(final Account.Id id) { super.setFrom(id); /** Is the from user in an email squelching group? */ final IdentifiedUser user = args.identifiedUserFactory.create(id); final Set<AccountGroup.UUID> gids = user.getEffectiveGroups(); for (final AccountGroup.UUID gid : gids) { if (args.groupCache.get(gid).isEmailOnlyAuthors()) { emailOnlyAuthors = true; break; } } }
public Response<String> apply(IdentifiedUser user, String newPassword) throws ResourceNotFoundException, ResourceConflictException, OrmException { if (user.getUserName() == null) { throw new ResourceConflictException("username must be set"); } AccountExternalId id = dbProvider .get() .accountExternalIds() .get(new AccountExternalId.Key(SCHEME_USERNAME, user.getUserName())); if (id == null) { throw new ResourceNotFoundException(); } id.setPassword(newPassword); dbProvider.get().accountExternalIds().update(Collections.singleton(id)); accountCache.evict(user.getAccountId()); return Strings.isNullOrEmpty(newPassword) ? Response.<String>none() : Response.ok(newPassword); }
String getMessage() { StringBuilder msg = new StringBuilder(); msg.append("\r\n"); msg.append(" **** Welcome to Gerrit Code Review ****\r\n"); msg.append("\r\n"); Account account = user.getAccount(); String name = account.getFullName(); if (name == null || name.isEmpty()) { name = user.getUserName(); } msg.append(" Hi "); msg.append(name); msg.append(", you have successfully connected over SSH."); msg.append("\r\n"); msg.append("\r\n"); msg.append(" Unfortunately, interactive shells are disabled.\r\n"); msg.append(" To clone a hosted Git repository, use:\r\n"); msg.append("\r\n"); if (!sshInfo.getHostKeys().isEmpty()) { String host = sshInfo.getHostKeys().get(0).getHost(); if (host.startsWith("*:")) { host = getGerritHost() + host.substring(1); } msg.append(" git clone ssh://"); msg.append(user.getUserName()); msg.append("@"); msg.append(host); msg.append("/"); msg.append("REPOSITORY_NAME.git"); msg.append("\r\n"); } msg.append("\r\n"); return msg.toString(); }
public AccountResource.SshKey parse(IdentifiedUser user, IdString id) throws ResourceNotFoundException, OrmException { try { int seq = Integer.parseInt(id.get(), 10); AccountSshKey sshKey = dbProvider.get().accountSshKeys().get(new AccountSshKey.Id(user.getAccountId(), seq)); if (sshKey == null) { throw new ResourceNotFoundException(id); } return new AccountResource.SshKey(user, sshKey); } catch (NumberFormatException e) { throw new ResourceNotFoundException(id); } }
private void assertScoreIsAllowed( final PatchSet.Id patchSetId, final ChangeControl changeControl, ApproveOption ao, Short v) throws UnloggedFailure { final PatchSetApproval psa = new PatchSetApproval( new PatchSetApproval.Key(patchSetId, currentUser.getAccountId(), ao.getCategoryId()), v); final FunctionState fs = functionStateFactory.create( changeControl.getChange(), patchSetId, Collections.<PatchSetApproval>emptyList()); psa.setValue(v); fs.normalize(approvalTypes.byId(psa.getCategoryId()), psa); if (v != psa.getValue()) { throw error(ao.name() + "=" + ao.value() + " not permitted"); } }
private BatchMetaDataUpdate approve( ChangeControl control, PatchSet.Id psId, IdentifiedUser user, ChangeUpdate update, Timestamp timestamp) throws OrmException { Map<PatchSetApproval.Key, PatchSetApproval> byKey = Maps.newHashMap(); for (PatchSetApproval psa : approvalsUtil.byPatchSet(db, control, psId)) { if (!byKey.containsKey(psa.getKey())) { byKey.put(psa.getKey(), psa); } } PatchSetApproval submit = new PatchSetApproval( new PatchSetApproval.Key(psId, user.getAccountId(), LabelId.SUBMIT), (short) 1, TimeUtil.nowTs()); byKey.put(submit.getKey(), submit); submit.setValue((short) 1); submit.setGranted(timestamp); // Flatten out existing approvals for this patch set based upon the current // permissions. Once the change is closed the approvals are not updated at // presentation view time, except for zero votes used to indicate a reviewer // was added. So we need to make sure votes are accurate now. This way if // permissions get modified in the future, historical records stay accurate. LabelNormalizer.Result normalized = labelNormalizer.normalize(control, byKey.values()); // TODO(dborowitz): Don't use a label in notedb; just check when status // change happened. update.putApproval(submit.getLabel(), submit.getValue()); logDebug("Adding submit label " + submit); db.patchSetApprovals().upsert(normalized.getNormalized()); db.patchSetApprovals().delete(normalized.deleted()); try { return saveToBatch(control, update, normalized, timestamp); } catch (IOException e) { throw new OrmException(e); } }
@Override public List<AccountExternalId> call() throws OrmException { final AccountExternalId.Key last = session.getLastLoginExternalId(); final List<AccountExternalId> ids = db.accountExternalIds().byAccount(user.getAccountId()).toList(); for (final AccountExternalId e : ids) { e.setTrusted(authConfig.isIdentityTrustable(Collections.singleton(e))); // The identity can be deleted only if its not the one used to // establish this web session, and if only if an identity was // actually used to establish this web session. // if (e.isScheme(SCHEME_USERNAME)) { e.setCanDelete(false); } else { e.setCanDelete(last != null && !last.equals(e.getKey())); } } return ids; }
@Override public GroupMembership membershipsOf(IdentifiedUser user) { String id = findId(user.state().getExternalIds()); if (id == null) { return GroupMembership.EMPTY; } try { final Set<AccountGroup.UUID> groups = membershipCache.get(id); return new ListGroupMembership(groups) { @Override public Set<AccountGroup.UUID> getKnownGroups() { Set<AccountGroup.UUID> g = Sets.newHashSet(groups); g.retainAll(projectCache.guessRelevantGroupUUIDs()); return g; } }; } catch (ExecutionException e) { log.warn(String.format("Cannot lookup membershipsOf %s in LDAP", id), e); return GroupMembership.EMPTY; } }
private void setApproval(ChangeData cd, IdentifiedUser user) throws OrmException, IOException { Timestamp timestamp = TimeUtil.nowTs(); ChangeControl control = cd.changeControl(); PatchSet.Id psId = cd.currentPatchSet().getId(); PatchSet.Id psIdNewRev = commits.get(cd.change().getId()).change().currentPatchSetId(); logDebug("Add approval for " + cd + " from user " + user); ChangeUpdate update = updateFactory.create(control, timestamp); update.putReviewer(user.getAccountId(), REVIEWER); List<SubmitRecord> record = records.get(cd.change().getId()); if (record != null) { update.merge(record); } db.changes().beginTransaction(cd.change().getId()); try { BatchMetaDataUpdate batch = approve(control, psId, user, update, timestamp); batch.write(update, new CommitBuilder()); // If the submit strategy created a new revision (rebase, cherry-pick) // approve that as well if (!psIdNewRev.equals(psId)) { update.setPatchSetId(psId); update.commit(); // Create a new ChangeUpdate instance because we need to store meta data // on another patch set (psIdNewRev). update = updateFactory.create(control, timestamp); batch = approve(control, psIdNewRev, user, update, timestamp); // Write update commit after all normalized label commits. batch.write(update, new CommitBuilder()); } db.commit(); } finally { db.rollback(); } update.commit(); indexer.index(db, cd.change()); }
private RefUpdate updateBranch(Branch.NameKey destBranch, IdentifiedUser caller) throws IntegrationException { RefUpdate branchUpdate = getPendingRefUpdate(destBranch); CodeReviewCommit branchTip = getBranchTip(destBranch); MergeTip mergeTip = mergeTips.get(destBranch); CodeReviewCommit currentTip = mergeTip != null ? mergeTip.getCurrentTip() : null; if (Objects.equals(branchTip, currentTip)) { if (currentTip != null) { logDebug("Branch already at merge tip {}, no update to perform", currentTip.name()); } else { logDebug("Both branch and merge tip are nonexistent, no update"); } return null; } else if (currentTip == null) { logDebug("No merge tip, no update to perform"); return null; } if (RefNames.REFS_CONFIG.equals(branchUpdate.getName())) { logDebug("Loading new configuration from {}", RefNames.REFS_CONFIG); try { ProjectConfig cfg = new ProjectConfig(destProject.getProject().getNameKey()); cfg.load(repo, currentTip); } catch (Exception e) { throw new IntegrationException( "Submit would store invalid" + " project configuration " + currentTip.name() + " for " + destProject.getProject().getName(), e); } } branchUpdate.setRefLogIdent( identifiedUserFactory.create(caller.getAccountId()).newRefLogIdent()); branchUpdate.setForceUpdate(false); branchUpdate.setNewObjectId(currentTip); branchUpdate.setRefLogMessage("merged", true); try { RefUpdate.Result result = branchUpdate.update(rw); logDebug( "Update of {}: {}..{} returned status {}", branchUpdate.getName(), branchUpdate.getOldObjectId(), branchUpdate.getNewObjectId(), result); switch (result) { case NEW: case FAST_FORWARD: if (branchUpdate.getResult() == RefUpdate.Result.FAST_FORWARD) { tagCache.updateFastForward( destBranch.getParentKey(), branchUpdate.getName(), branchUpdate.getOldObjectId(), currentTip); } if (RefNames.REFS_CONFIG.equals(branchUpdate.getName())) { Project p = destProject.getProject(); projectCache.evict(p); destProject = projectCache.get(p.getNameKey()); repoManager.setProjectDescription(p.getNameKey(), p.getDescription()); } return branchUpdate; case LOCK_FAILURE: throw new IntegrationException("Failed to lock " + branchUpdate.getName()); default: throw new IOException(branchUpdate.getResult().name() + '\n' + branchUpdate); } } catch (IOException e) { throw new IntegrationException("Cannot update " + branchUpdate.getName(), e); } }
private String[] makeEnv(final HttpServletRequest req, final ProjectControl project) { final EnvList env = new EnvList(_env); final int contentLength = Math.max(0, req.getContentLength()); // These ones are from "The WWW Common Gateway Interface Version 1.1" // env.set("AUTH_TYPE", req.getAuthType()); env.set("CONTENT_LENGTH", Integer.toString(contentLength)); env.set("CONTENT_TYPE", req.getContentType()); env.set("GATEWAY_INTERFACE", "CGI/1.1"); env.set("PATH_INFO", req.getPathInfo()); env.set("PATH_TRANSLATED", null); env.set("QUERY_STRING", req.getQueryString()); env.set("REMOTE_ADDR", req.getRemoteAddr()); env.set("REMOTE_HOST", req.getRemoteHost()); env.set("HTTPS", req.isSecure() ? "ON" : "OFF"); // The identity information reported about the connection by a // RFC 1413 [11] request to the remote agent, if // available. Servers MAY choose not to support this feature, or // not to request the data for efficiency reasons. // "REMOTE_IDENT" => "NYI" // env.set("REQUEST_METHOD", req.getMethod()); env.set("SCRIPT_NAME", req.getContextPath() + req.getServletPath()); env.set("SCRIPT_FILENAME", gitwebCgi.toAbsolutePath().toString()); env.set("SERVER_NAME", req.getServerName()); env.set("SERVER_PORT", Integer.toString(req.getServerPort())); env.set("SERVER_PROTOCOL", req.getProtocol()); env.set("SERVER_SOFTWARE", getServletContext().getServerInfo()); final Enumeration<String> hdrs = enumerateHeaderNames(req); while (hdrs.hasMoreElements()) { final String name = hdrs.nextElement(); final String value = req.getHeader(name); env.set("HTTP_" + name.toUpperCase().replace('-', '_'), value); } env.set("GERRIT_CONTEXT_PATH", req.getContextPath() + "/"); env.set("GERRIT_PROJECT_NAME", project.getProject().getName()); if (project.forUser(anonymousUserProvider.get()).isVisible()) { env.set("GERRIT_ANONYMOUS_READ", "1"); } String remoteUser = null; if (project.getCurrentUser().isIdentifiedUser()) { final IdentifiedUser u = (IdentifiedUser) project.getCurrentUser(); final String user = u.getUserName(); env.set("GERRIT_USER_NAME", user); if (user != null && !user.isEmpty()) { remoteUser = user; } else { remoteUser = "******" + u.getAccountId(); } } env.set("REMOTE_USER", remoteUser); // Override CGI settings using alternative URI provided by gitweb.url. // This is required to trick gitweb into thinking that it's served under // different URL. Setting just $my_uri on the perl's side isn't enough, // because few actions (atom, blobdiff_plain, commitdiff_plain) rely on // URL returned by $cgi->self_url(). // if (gitwebUrl != null) { int schemePort = -1; if (gitwebUrl.getScheme() != null) { if (gitwebUrl.getScheme().equals("http")) { env.set("HTTPS", "OFF"); schemePort = 80; } else { env.set("HTTPS", "ON"); schemePort = 443; } } if (gitwebUrl.getHost() != null) { env.set("SERVER_NAME", gitwebUrl.getHost()); env.set("HTTP_HOST", gitwebUrl.getHost()); } if (gitwebUrl.getPort() != -1) { env.set("SERVER_PORT", Integer.toString(gitwebUrl.getPort())); } else if (schemePort != -1) { env.set("SERVER_PORT", Integer.toString(schemePort)); } if (gitwebUrl.getPath() != null) { env.set("SCRIPT_NAME", gitwebUrl.getPath().isEmpty() ? "/" : gitwebUrl.getPath()); } } return env.getEnvArray(); }
@Override public void onPreMerge( final Repository repo, final CodeReviewCommit commit, final ProjectState destProject, final Branch.NameKey destBranch, final PatchSet.Id patchSetId) throws MergeValidationException { if (RefNames.REFS_CONFIG.equals(destBranch.get())) { final Project.NameKey newParent; try { ProjectConfig cfg = new ProjectConfig(destProject.getProject().getNameKey()); cfg.load(repo, commit); newParent = cfg.getProject().getParent(allProjectsName); final Project.NameKey oldParent = destProject.getProject().getParent(allProjectsName); if (oldParent == null) { // update of the 'All-Projects' project if (newParent != null) { throw new MergeValidationException(ROOT_NO_PARENT); } } else { if (!oldParent.equals(newParent)) { PatchSetApproval psa = approvalsUtil.getSubmitter(db, commit.notes(), patchSetId); if (psa == null) { throw new MergeValidationException(SET_BY_ADMIN); } final IdentifiedUser submitter = identifiedUserFactory.create(psa.getAccountId()); if (!submitter.getCapabilities().canAdministrateServer()) { throw new MergeValidationException(SET_BY_ADMIN); } if (projectCache.get(newParent) == null) { throw new MergeValidationException(PARENT_NOT_FOUND); } } } for (Entry<ProjectConfigEntry> e : pluginConfigEntries) { PluginConfig pluginCfg = cfg.getPluginConfig(e.getPluginName()); ProjectConfigEntry configEntry = e.getProvider().get(); String value = pluginCfg.getString(e.getExportName()); String oldValue = destProject .getConfig() .getPluginConfig(e.getPluginName()) .getString(e.getExportName()); if ((value == null ? oldValue != null : !value.equals(oldValue)) && !configEntry.isEditable(destProject)) { throw new MergeValidationException(PLUGIN_VALUE_NOT_EDITABLE); } if (ProjectConfigEntry.Type.LIST.equals(configEntry.getType()) && value != null && !configEntry.getPermittedValues().contains(value)) { throw new MergeValidationException(PLUGIN_VALUE_NOT_PERMITTED); } } } catch (ConfigInvalidException | IOException e) { throw new MergeValidationException(INVALID_CONFIG); } } }