update labels rls
This commit is contained in:
@ -178,9 +178,9 @@ export const updateHighlightResolver = authorized<
|
||||
const updatedHighlight = await updateHighlight(
|
||||
input.highlightId,
|
||||
{
|
||||
annotation: input.annotation,
|
||||
html: input.html,
|
||||
quote: input.quote,
|
||||
annotation: input.annotation ?? undefined,
|
||||
html: input.html ?? undefined,
|
||||
quote: input.quote ?? undefined,
|
||||
},
|
||||
uid,
|
||||
pubsub
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
WebhookSuccess,
|
||||
} from '../../generated/graphql'
|
||||
import { authTrx } from '../../repository'
|
||||
import { deleteWebhook } from '../../services/webhook'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
|
||||
@ -80,9 +81,9 @@ export const deleteWebhookResolver = authorized<
|
||||
DeleteWebhookSuccess,
|
||||
DeleteWebhookError,
|
||||
MutationDeleteWebhookArgs
|
||||
>(async (_, { id }, { authTrx, uid, log }) => {
|
||||
>(async (_, { id }, { uid, log }) => {
|
||||
try {
|
||||
await authTrx(async (t) => t.getRepository(Webhook).delete(id))
|
||||
const webhook = await deleteWebhook(id, uid)
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
@ -94,16 +95,7 @@ export const deleteWebhookResolver = authorized<
|
||||
})
|
||||
|
||||
return {
|
||||
webhook: {
|
||||
id,
|
||||
url: '',
|
||||
eventTypes: [],
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
enabled: false,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
webhook: webhookDataToResponse(webhook),
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('Error deleting webhook', error)
|
||||
|
||||
@ -76,8 +76,11 @@ export const updateHighlight = async (
|
||||
const highlightRepo = tx.withRepository(highlightRepository)
|
||||
await highlightRepo.updateAndSave(highlightId, highlight)
|
||||
|
||||
return highlightRepo.findOneByOrFail({
|
||||
id: highlightId,
|
||||
return highlightRepo.findOneOrFail({
|
||||
where: { id: highlightId },
|
||||
relations: {
|
||||
libraryItem: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -190,3 +190,23 @@ export const updateLabel = async (
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const findLabelsByUserId = async (userId: string): Promise<Label[]> => {
|
||||
return authTrx(
|
||||
async (tx) =>
|
||||
tx.withRepository(labelRepository).find({
|
||||
where: { user: { id: userId } },
|
||||
order: { position: 'ASC' },
|
||||
}),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const findLabelById = async (id: string, userId: string) => {
|
||||
return authTrx(
|
||||
async (tx) => tx.withRepository(labelRepository).findOneBy({ id }),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import { BulkActionType } from '../generated/graphql'
|
||||
import { createPubSubClient, EntityType } from '../pubsub'
|
||||
import { authTrx } from '../repository'
|
||||
import { libraryItemRepository } from '../repository/library_item'
|
||||
import { wordsCount } from '../utils/helpers'
|
||||
import {
|
||||
DateFilter,
|
||||
FieldFilter,
|
||||
@ -387,7 +388,13 @@ export const createLibraryItem = async (
|
||||
pubsub = createPubSubClient()
|
||||
): Promise<LibraryItem> => {
|
||||
const newLibraryItem = await authTrx(
|
||||
async (tx) => tx.withRepository(libraryItemRepository).save(libraryItem),
|
||||
async (tx) =>
|
||||
tx.withRepository(libraryItemRepository).save({
|
||||
...libraryItem,
|
||||
wordCount:
|
||||
libraryItem.wordCount ??
|
||||
wordsCount(libraryItem.readableContent || ''),
|
||||
}),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
|
||||
@ -5,7 +5,7 @@ import { DeepPartial, EntityManager } from 'typeorm'
|
||||
import { LibraryItem, LibraryItemType } from '../entity/library_item'
|
||||
import { authTrx, entityManager } from '../repository'
|
||||
import { libraryItemRepository } from '../repository/library_item'
|
||||
import { generateSlug, stringToHash } from '../utils/helpers'
|
||||
import { generateSlug, stringToHash, wordsCount } from '../utils/helpers'
|
||||
import { logger } from '../utils/logger'
|
||||
import { createLibraryItem } from './library_item'
|
||||
|
||||
@ -75,6 +75,7 @@ const popularReadToLibraryItem = (
|
||||
publishedAt: pr.publishedAt,
|
||||
siteName: pr.siteName,
|
||||
user: { id: userId },
|
||||
wordCount: wordsCount(pr.content),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -36,9 +36,9 @@ export const deleteRule = async (id: string, userId?: string) => {
|
||||
return authTrx(
|
||||
async (t) => {
|
||||
const repo = t.getRepository(Rule)
|
||||
const rule = await repo.findOneByOrFail({ id })
|
||||
await repo.delete(id)
|
||||
|
||||
return repo.findOneByOrFail({ id })
|
||||
return rule
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
|
||||
@ -41,3 +41,16 @@ export const findWebhookById = async (id: string, userId?: string) => {
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const deleteWebhook = async (id: string, userId?: string) => {
|
||||
return authTrx(
|
||||
async (tx) => {
|
||||
const repo = tx.getRepository(Webhook)
|
||||
const webhook = await repo.findOneByOrFail({ id })
|
||||
await repo.delete(id)
|
||||
return webhook
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
@ -5,12 +5,17 @@ import { Highlight } from '../../src/entity/highlight'
|
||||
import { Label } from '../../src/entity/label'
|
||||
import { LibraryItem } from '../../src/entity/library_item'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import {
|
||||
createHighlight,
|
||||
findHighlightById,
|
||||
} from '../../src/services/highlights'
|
||||
import { createLabel, deleteLabels, saveLabelsInHighlight } from '../../src/services/labels'
|
||||
import {
|
||||
createLabel,
|
||||
deleteLabels,
|
||||
findLabelById,
|
||||
findLabelsByUserId,
|
||||
saveLabelsInHighlight,
|
||||
} from '../../src/services/labels'
|
||||
import {
|
||||
deleteLibraryItemById,
|
||||
findLibraryItemById,
|
||||
@ -38,22 +43,17 @@ describe('Labels API', () => {
|
||||
})
|
||||
|
||||
describe('GET labels', () => {
|
||||
let labels: Label[]
|
||||
let query: string
|
||||
|
||||
before(async () => {
|
||||
// create testing labels
|
||||
const label1 = await createLabel('label_1', '#ffffff', user.id)
|
||||
const label2 = await createLabel('label_2', '#eeeeee', user.id)
|
||||
labels = [label1, label2]
|
||||
await createLabel('label_1', '#ffffff', user.id)
|
||||
await createLabel('label_2', '#eeeeee', user.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
user.id
|
||||
)
|
||||
await deleteLabels({ user: { id: user.id } }, user.id)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
@ -80,9 +80,7 @@ describe('Labels API', () => {
|
||||
it('should return labels', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
const labels = await getRepository(Label).findBy({
|
||||
user: { id: user.id },
|
||||
})
|
||||
const labels = await findLabelsByUserId(user.id)
|
||||
expect(res.body.data.labels.labels).to.eql(
|
||||
labels.map((label) => ({
|
||||
id: label.id,
|
||||
@ -148,9 +146,10 @@ describe('Labels API', () => {
|
||||
|
||||
it('should create label', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
const label = await getRepository(Label).findOneBy({
|
||||
id: res.body.data.createLabel.label.id,
|
||||
})
|
||||
const label = await findLabelById(
|
||||
res.body.data.createLabel.label.id,
|
||||
user.id
|
||||
)
|
||||
expect(label).to.exist
|
||||
})
|
||||
})
|
||||
@ -164,15 +163,13 @@ describe('Labels API', () => {
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteLabels([existingLabel.id], user.id)
|
||||
await deleteLabels({ id: existingLabel.id }, user.id)
|
||||
})
|
||||
|
||||
it('should return error code BAD_REQUEST', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
expect(res.body.data.createLabel.errorCodes).to.eql([
|
||||
'BAD_REQUEST',
|
||||
])
|
||||
expect(res.body.data.createLabel.errorCodes).to.eql(['BAD_REQUEST'])
|
||||
})
|
||||
})
|
||||
|
||||
@ -228,7 +225,7 @@ describe('Labels API', () => {
|
||||
|
||||
it('should delete label', async () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
const label = await getRepository(Label).findOneBy({ id: labelId })
|
||||
const label = await findLabelById(labelId, user.id)
|
||||
expect(label).not.exist
|
||||
})
|
||||
})
|
||||
@ -335,7 +332,7 @@ describe('Labels API', () => {
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
{ user: { id: user.id } },
|
||||
user.id
|
||||
)
|
||||
await deleteLibraryItemById(item.id)
|
||||
@ -461,7 +458,7 @@ describe('Labels API', () => {
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteLabels([toUpdateLabel.id], user.id)
|
||||
await deleteLabels( { id: toUpdateLabel.id }, user.id)
|
||||
})
|
||||
|
||||
it('should return the updated label', async () => {
|
||||
@ -475,9 +472,7 @@ describe('Labels API', () => {
|
||||
|
||||
it('should update the label in db', async () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
const updatedLabel = await getRepository(Label).findOne({
|
||||
where: { id: labelId },
|
||||
})
|
||||
const updatedLabel = await findLabelById(labelId, user.id)
|
||||
|
||||
expect(updatedLabel?.name).to.eql(name)
|
||||
expect(updatedLabel?.color).to.eql(color)
|
||||
@ -538,7 +533,7 @@ describe('Labels API', () => {
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
{ user: { id: user.id } },
|
||||
user.id
|
||||
)
|
||||
await deleteLibraryItemById(item.id)
|
||||
@ -689,12 +684,7 @@ describe('Labels API', () => {
|
||||
expect(res.body.data.moveLabel.label.position).to.eql(
|
||||
labels[4].position
|
||||
)
|
||||
const reorderedLabels = await getRepository(Label).find({
|
||||
where: {
|
||||
user: { id: user.id },
|
||||
},
|
||||
order: { position: 'ASC' },
|
||||
})
|
||||
const reorderedLabels = await findLabelsByUserId(user.id)
|
||||
expect(reorderedLabels.map((l) => l.id)).to.eql([
|
||||
labels[0].id,
|
||||
labels[2].id,
|
||||
|
||||
@ -42,7 +42,7 @@ describe('PopularReads API', () => {
|
||||
|
||||
describe('addPopularRead', () => {
|
||||
it('should add a new article if the readName is valid', async () => {
|
||||
const readName = 'omnivore_get_started'
|
||||
const readName = 'omnivore_ios'
|
||||
const res = await graphqlRequest(
|
||||
addPopularReadQuery(readName),
|
||||
authToken
|
||||
@ -54,14 +54,14 @@ describe('PopularReads API', () => {
|
||||
user.id
|
||||
)
|
||||
expect(item?.originalUrl).to.eq(
|
||||
'https://blog.omnivore.app/p/getting-started-with-omnivore'
|
||||
'https://blog.omnivore.app/p/saving-links-from-your-iphone-or'
|
||||
)
|
||||
expect(item?.wordCount).to.eq(1155)
|
||||
expect(item?.wordCount).to.eq(371)
|
||||
})
|
||||
|
||||
it('responds status code 500 when invalid user', async () => {
|
||||
const invalidAuthToken = 'Fake token'
|
||||
const readName = 'omnivore_get_started'
|
||||
const readName = 'omnivore_web'
|
||||
return graphqlRequest(
|
||||
addPopularReadQuery(readName),
|
||||
invalidAuthToken
|
||||
|
||||
@ -146,7 +146,10 @@ describe('Recent Emails Resolver', () => {
|
||||
|
||||
expect(resp.body.data.markEmailAsItem.success).to.be.true
|
||||
|
||||
const updatedRecentEmail = await findReceivedEmailById(recentEmail.id)
|
||||
const updatedRecentEmail = await findReceivedEmailById(
|
||||
recentEmail.id,
|
||||
user.id
|
||||
)
|
||||
expect(updatedRecentEmail?.type).to.eql('article')
|
||||
})
|
||||
})
|
||||
|
||||
@ -16,6 +16,8 @@ CREATE POLICY integrations_policy on omnivore.integrations
|
||||
WITH CHECK (user_id = omnivore.get_current_user_id());
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON omnivore.integrations TO omnivore_user;
|
||||
|
||||
DROP POLICY read_labels ON omnivore.labels;
|
||||
DROP POLICY create_labels ON omnivore.labels;
|
||||
CREATE POLICY labels_policy on omnivore.labels
|
||||
USING (user_id = omnivore.get_current_user_id())
|
||||
WITH CHECK (user_id = omnivore.get_current_user_id());
|
||||
@ -38,6 +40,8 @@ CREATE POLICY webhooks_policy on omnivore.webhooks
|
||||
WITH CHECK (user_id = omnivore.get_current_user_id());
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON omnivore.webhooks TO omnivore_user;
|
||||
|
||||
DROP POLICY read_user_device_tokens ON omnivore.user_device_tokens;
|
||||
DROP POLICY create_user_device_tokens ON omnivore.user_device_tokens;
|
||||
CREATE POLICY user_device_tokens_policy on omnivore.user_device_tokens
|
||||
USING (user_id = omnivore.get_current_user_id())
|
||||
WITH CHECK (user_id = omnivore.get_current_user_id());
|
||||
|
||||
@ -11,6 +11,12 @@ ALTER TABLE omnivore.integrations DISABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY integrations_policy on omnivore.integrations;
|
||||
|
||||
DROP POLICY labels_policy on omnivore.labels;
|
||||
CREATE POLICY read_labels on omnivore.labels
|
||||
FOR SELECT TO omnivore_user
|
||||
USING (true);
|
||||
CREATE POLICY create_labels on omnivore.labels
|
||||
FOR INSERT TO omnivore_user
|
||||
WITH CHECK (true);
|
||||
|
||||
ALTER TABLE omnivore.received_emails DISABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY received_emails_policy on omnivore.received_emails;
|
||||
@ -22,5 +28,11 @@ ALTER TABLE omnivore.webhooks DISABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY webhooks_policy on omnivore.webhooks;
|
||||
|
||||
DROP POLICY user_device_tokens_policy on omnivore.user_device_tokens;
|
||||
CREATE POLICY read_user_device_tokens on omnivore.user_device_tokens
|
||||
FOR SELECT TO omnivore_user
|
||||
USING (true);
|
||||
CREATE POLICY create_user_device_tokens on omnivore.user_device_tokens
|
||||
FOR INSERT TO omnivore_user
|
||||
WITH CHECK (true);
|
||||
|
||||
COMMIT;
|
||||
|
||||
Reference in New Issue
Block a user