Skip to content

Commit

Permalink
fix storing jsonb-null propertyValue
Browse files Browse the repository at this point in the history
  • Loading branch information
brontolosone committed Sep 18, 2024
1 parent 4150a96 commit e514b52
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
10 changes: 8 additions & 2 deletions lib/model/query/user-preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@ const _writeProperty = (tablename, subject, userId, propertyName, propertyValue)
.concat((subject === null) ? [] : ['projectId'])
.map(el => sql.identifier([el]));

const values = [userId, propertyName, sql.json(propertyValue)]
// Work around null confusion (potential Slonik bug?).
// sql.json(null) doesn't produce what we need, it results in an exception
// "Error: Required parameter propertyValue missing."
// Yet the string 'null' (as distinct from the *jsonb* string '"null"' one would get with sql.json('null') !)
// gets properly casted by PostgreSQL to a jsonb null (as distinct from an SQL NULL), so we use that in this case.
const preparedPropertyValue = (propertyValue === null) ? 'null': sql.json(propertyValue);
const values = [userId, propertyName, preparedPropertyValue]
.concat((subject === null) ? [] : [subject]);

return one(sql`
Expand All @@ -75,7 +81,7 @@ const _writeProperty = (tablename, subject, userId, propertyName, propertyValue)
(${sql.join(values, `, `)})
ON CONFLICT ON CONSTRAINT ${sql.identifier([`${tablename}_primary_key`])}
DO UPDATE
SET "propertyValue" = ${sql.json(propertyValue)}
SET "propertyValue" = ${preparedPropertyValue}
RETURNING
1 AS "modified_count"
`);
Expand Down
21 changes: 21 additions & 0 deletions test/integration/api/user-preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@ const { testService } = require('../setup');

describe('api: user-preferences', () => {

it('can store a JS null propertyValue', testService(async (service) => {
const asAlice = await service.login('alice');

await asAlice.put('/v1/user-preferences/site/let-us-store-a-null')
.send({ propertyValue: null })
.expect(200);

await asAlice.get('/v1/users/current')
.set('X-Extended-Metadata', 'true')
.expect(200)
.then(({ body }) => {
body.preferences.should.eql({
site: {
'let-us-store-a-null': null,
},
projects: {
},
});
});
}));

it('should not allow storing preferences for nonexistent projects', testService(async (service) => {
const asAlice = await service.login('alice');

Expand Down

0 comments on commit e514b52

Please sign in to comment.