Skip to content

Commit

Permalink
fix(server): support partial id lookup on postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickhulce committed Nov 8, 2019
1 parent 696a95e commit 26024ff
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
33 changes: 30 additions & 3 deletions packages/server/src/api/storage/sql/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const path = require('path');
const uuid = require('uuid');
const Umzug = require('umzug');
const Sequelize = require('sequelize');
const {omit} = require('@lhci/utils/src/lodash.js');
const {omit, padEnd} = require('@lhci/utils/src/lodash.js');
const {E422} = require('../../express-utils.js');
const StorageMethod = require('../storage-method.js');
const projectModelDefn = require('./project-model.js');
Expand Down Expand Up @@ -40,6 +40,17 @@ function isUuid(id) {
);
}

/**
* @param {string} uuid
* @param {string} filler
*/
function formatAsUuid(uuid, filler = '0') {
const parts = padEnd(uuid, 32, filler).match(/\w{4}/g);
if (!parts || parts.length !== 8) throw new Error('Invalid UUID');
const [p1, p2, p3, p4, p5, p6, p7, p8] = parts;
return `${p1}${p2}-${p3}-${p4}-${p5}-${p6}${p7}${p8}`;
}

/**
* @param {string|undefined} id
*/
Expand Down Expand Up @@ -357,10 +368,26 @@ class SqlStorageMethod {
*/
async findBuildById(projectId, buildId) {
const {buildModel} = this._sql();
if (isUuid(buildId)) {
const build = await this._findByPk(buildModel, buildId);
if (build && build.projectId !== projectId) return undefined;
return clone(build || undefined);
}

if (!validatePartialUuidOrUndefined(buildId)) return undefined;
const idMatch = isUuid(buildId) ? buildId : {[Sequelize.Op.like]: `${buildId}%`};

// Postgres stores UUIDs as numbers so it's impossible to do a pattern match.
// Instead we'll do a range check which works whether the UUID is treated as a string or a
// number. For example...
//
// Given the prefix `a82fb732` we can look for all UUIDs that are...
// >= a82fb732-0000-0000-0000-000000000000
// <= a82fb732-ffff-ffff-ffff-ffffffffffff
const numericValue = parseInt(buildId.replace(/-/g, ''), 16);
const lowerUuid = formatAsUuid(numericValue.toString(16), '0');
const upperUuid = formatAsUuid(numericValue.toString(16), 'f');
const builds = await buildModel.findAll({
where: {id: idMatch, projectId},
where: {id: {[Sequelize.Op.gte]: lowerUuid, [Sequelize.Op.lte]: upperUuid}, projectId},
limit: 2,
});

Expand Down
9 changes: 9 additions & 0 deletions packages/utils/src/lodash.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ module.exports = {
if (s.length >= length) return s;
return `${padding.repeat(length)}${s}`.slice(-length);
},
/**
* @param {string} s
* @param {number} length
* @param {string} [padding]
*/
padEnd(s, length, padding = ' ') {
if (s.length >= length) return s;
return `${s}${padding.repeat(length)}`.slice(0, length);
},
/**
* Deep clones an object via JSON.parse/JSON.stringify.
* @template T
Expand Down

0 comments on commit 26024ff

Please sign in to comment.