mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
fix some rls issue
This commit is contained in:
parent
cea5f790d8
commit
669cddeec8
55 changed files with 689 additions and 627 deletions
|
|
@ -14,6 +14,7 @@ import {
|
|||
RevokeApiKeySuccess,
|
||||
} from '../../generated/graphql'
|
||||
import { getRepository } from '../../repository'
|
||||
import { findApiKeys } from '../../services/api_key'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { generateApiKey, hashApiKey } from '../../utils/auth'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
|
|
@ -21,14 +22,7 @@ import { authorized } from '../../utils/helpers'
|
|||
export const apiKeysResolver = authorized<ApiKeysSuccess, ApiKeysError>(
|
||||
async (_, __, { log, uid }) => {
|
||||
try {
|
||||
const apiKeys = await getRepository(ApiKey).find({
|
||||
select: ['id', 'name', 'scopes', 'expiresAt', 'createdAt', 'usedAt'],
|
||||
where: { user: { id: uid } },
|
||||
order: {
|
||||
usedAt: { direction: 'DESC', nulls: 'last' },
|
||||
createdAt: 'DESC',
|
||||
},
|
||||
})
|
||||
const apiKeys = await findApiKeys(uid)
|
||||
|
||||
return {
|
||||
apiKeys,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { DeepPartial } from 'typeorm'
|
||||
import { Integration, IntegrationType } from '../../entity/integration'
|
||||
import { User } from '../../entity/user'
|
||||
import { env } from '../../env'
|
||||
import {
|
||||
DeleteIntegrationError,
|
||||
|
|
@ -18,8 +18,14 @@ import {
|
|||
SetIntegrationErrorCode,
|
||||
SetIntegrationSuccess,
|
||||
} from '../../generated/graphql'
|
||||
import { getRepository } from '../../repository'
|
||||
import { getIntegrationService } from '../../services/integrations'
|
||||
import {
|
||||
createIntegration,
|
||||
findIntegration,
|
||||
findIntegrations,
|
||||
getIntegrationService,
|
||||
removeIntegration,
|
||||
updateIntegration,
|
||||
} from '../../services/integrations'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import {
|
||||
deleteTask,
|
||||
|
|
@ -32,29 +38,17 @@ export const setIntegrationResolver = authorized<
|
|||
SetIntegrationSuccess,
|
||||
SetIntegrationError,
|
||||
MutationSetIntegrationArgs
|
||||
>(async (_, { input }, { claims: { uid }, log }) => {
|
||||
log.info('setIntegrationResolver')
|
||||
|
||||
>(async (_, { input }, { uid, log }) => {
|
||||
try {
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [SetIntegrationErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const integrationToSave: Partial<Integration> = {
|
||||
const integrationToSave: DeepPartial<Integration> = {
|
||||
...input,
|
||||
user,
|
||||
user: { id: uid },
|
||||
id: input.id || undefined,
|
||||
type: input.type || IntegrationType.Export,
|
||||
}
|
||||
if (input.id) {
|
||||
// Update
|
||||
const existingIntegration = await getRepository(Integration).findOne({
|
||||
where: { id: input.id },
|
||||
relations: ['user'],
|
||||
})
|
||||
const existingIntegration = await findIntegration({ id: input.id }, uid)
|
||||
if (!existingIntegration) {
|
||||
return {
|
||||
errorCodes: [SetIntegrationErrorCode.NotFound],
|
||||
|
|
@ -82,18 +76,18 @@ export const setIntegrationResolver = authorized<
|
|||
}
|
||||
|
||||
// save integration
|
||||
const integration = await getRepository(Integration).save(integrationToSave)
|
||||
const integration = await createIntegration(integrationToSave, uid)
|
||||
|
||||
if (
|
||||
integrationToSave.type === IntegrationType.Export &&
|
||||
(!integrationToSave.id || integrationToSave.enabled)
|
||||
) {
|
||||
// create a task to sync all the pages if new integration or enable integration (export type)
|
||||
const taskName = await enqueueSyncWithIntegration(user.id, input.name)
|
||||
const taskName = await enqueueSyncWithIntegration(uid, input.name)
|
||||
log.info('enqueued task', taskName)
|
||||
|
||||
// update task name in integration
|
||||
await getRepository(Integration).update(integration.id, { taskName })
|
||||
await updateIntegration(integration.id, { taskName }, uid)
|
||||
integration.taskName = taskName
|
||||
} else if (integrationToSave.taskName) {
|
||||
// delete the task if disable integration and task exists
|
||||
|
|
@ -101,9 +95,13 @@ export const setIntegrationResolver = authorized<
|
|||
log.info('task deleted', integrationToSave.taskName)
|
||||
|
||||
// update task name in integration
|
||||
await getRepository(Integration).update(integration.id, {
|
||||
taskName: null,
|
||||
})
|
||||
await updateIntegration(
|
||||
integration.id,
|
||||
{
|
||||
taskName: null,
|
||||
},
|
||||
uid
|
||||
)
|
||||
integration.taskName = null
|
||||
}
|
||||
|
||||
|
|
@ -131,19 +129,9 @@ export const setIntegrationResolver = authorized<
|
|||
export const integrationsResolver = authorized<
|
||||
IntegrationsSuccess,
|
||||
IntegrationsError
|
||||
>(async (_, __, { claims: { uid }, log }) => {
|
||||
log.info('integrationsResolver')
|
||||
|
||||
>(async (_, __, { uid, log }) => {
|
||||
try {
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [IntegrationsErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
const integrations = await getRepository(Integration).findBy({
|
||||
user: { id: uid },
|
||||
})
|
||||
const integrations = await findIntegrations(uid)
|
||||
|
||||
return {
|
||||
integrations,
|
||||
|
|
@ -165,17 +153,7 @@ export const deleteIntegrationResolver = authorized<
|
|||
log.info('deleteIntegrationResolver')
|
||||
|
||||
try {
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [DeleteIntegrationErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const integration = await getRepository(Integration).findOne({
|
||||
where: { id },
|
||||
relations: ['user'],
|
||||
})
|
||||
const integration = await findIntegration({ id }, uid)
|
||||
|
||||
if (!integration) {
|
||||
return {
|
||||
|
|
@ -183,21 +161,13 @@ export const deleteIntegrationResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
if (integration.user.id !== uid) {
|
||||
return {
|
||||
errorCodes: [DeleteIntegrationErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
if (integration.taskName) {
|
||||
// delete the task if task exists
|
||||
await deleteTask(integration.taskName)
|
||||
log.info('task deleted', integration.taskName)
|
||||
}
|
||||
|
||||
const deletedIntegration = await getRepository(Integration).remove(
|
||||
integration
|
||||
)
|
||||
const deletedIntegration = await removeIntegration(integration, uid)
|
||||
deletedIntegration.id = id
|
||||
|
||||
analytics.track({
|
||||
|
|
@ -229,10 +199,7 @@ export const importFromIntegrationResolver = authorized<
|
|||
log.info('importFromIntegrationResolver')
|
||||
|
||||
try {
|
||||
const integration = await getRepository(Integration).findOne({
|
||||
where: { id: integrationId, user: { id: uid } },
|
||||
relations: ['user'],
|
||||
})
|
||||
const integration = await findIntegration({ id: integrationId }, uid)
|
||||
|
||||
if (!integration) {
|
||||
return {
|
||||
|
|
@ -251,7 +218,7 @@ export const importFromIntegrationResolver = authorized<
|
|||
authToken
|
||||
)
|
||||
// update task name in integration
|
||||
await getRepository(Integration).update(integration.id, { taskName })
|
||||
await updateIntegration(integration.id, { taskName }, uid)
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ import {
|
|||
import {
|
||||
createDeviceToken,
|
||||
deleteDeviceToken,
|
||||
getDeviceToken,
|
||||
getDeviceTokenByToken,
|
||||
getDeviceTokensByUserId,
|
||||
findDeviceTokenById,
|
||||
findDeviceTokenByToken,
|
||||
findDeviceTokensByUserId,
|
||||
} from '../../services/user_device_tokens'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { authorized } from '../../utils/helpers'
|
||||
|
|
@ -44,7 +44,7 @@ export const setDeviceTokenResolver = authorized<
|
|||
try {
|
||||
// when token is null, we are deleting it
|
||||
if (!token && id) {
|
||||
const deviceToken = await getDeviceToken(id)
|
||||
const deviceToken = await findDeviceTokenById(id)
|
||||
if (!deviceToken) {
|
||||
log.error('device token not found', id)
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ export const setDeviceTokenResolver = authorized<
|
|||
token
|
||||
) {
|
||||
// duplicate token
|
||||
const deviceToken = await getDeviceTokenByToken(token)
|
||||
const deviceToken = await findDeviceTokenByToken(token)
|
||||
|
||||
if (!deviceToken) {
|
||||
return {
|
||||
|
|
@ -139,7 +139,7 @@ export const deviceTokensResolver = authorized<
|
|||
},
|
||||
})
|
||||
|
||||
const deviceTokens = await getDeviceTokensByUserId(uid)
|
||||
const deviceTokens = await findDeviceTokensByUserId(uid)
|
||||
log.info('deviceTokens', deviceTokens)
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import express from 'express'
|
|||
import * as jwt from 'jsonwebtoken'
|
||||
import { env } from '../env'
|
||||
import { Claims } from '../resolvers/types'
|
||||
import { getDeviceTokensByUserId } from '../services/user_device_tokens'
|
||||
import { findDeviceTokensByUserId } from '../services/user_device_tokens'
|
||||
import { corsConfig } from '../utils/corsConfig'
|
||||
import {
|
||||
PushNotificationType,
|
||||
|
|
@ -42,7 +42,7 @@ export function notificationRouter() {
|
|||
return res.status(400).send({ errorCode: 'BAD_DATA' })
|
||||
}
|
||||
|
||||
const tokens = await getDeviceTokensByUserId(userId)
|
||||
const tokens = await findDeviceTokensByUserId(userId)
|
||||
if (tokens.length === 0) {
|
||||
return res.status(400).send({ errorCode: 'NO_DEVICE_TOKENS' })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { env } from '../../env'
|
|||
import { UploadFileStatus } from '../../generated/graphql'
|
||||
import { authTrx } from '../../repository'
|
||||
import { createLibraryItem } from '../../services/library_item'
|
||||
import { getNewsletterEmail } from '../../services/newsletters'
|
||||
import { findNewsletterEmail } from '../../services/newsletters'
|
||||
import { updateReceivedEmail } from '../../services/received_emails'
|
||||
import {
|
||||
findUploadFileById,
|
||||
|
|
@ -45,7 +45,7 @@ export function emailAttachmentRouter() {
|
|||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
|
||||
const newsletterEmail = await getNewsletterEmail(email)
|
||||
const newsletterEmail = await findNewsletterEmail(email)
|
||||
if (!newsletterEmail || !newsletterEmail.user) {
|
||||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ export function emailAttachmentRouter() {
|
|||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
|
||||
const newsletterEmail = await getNewsletterEmail(email)
|
||||
const newsletterEmail = await findNewsletterEmail(email)
|
||||
if (!newsletterEmail || !newsletterEmail.user) {
|
||||
return res.status(401).send('UNAUTHORIZED')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import cors from 'cors'
|
|||
import express from 'express'
|
||||
import { env } from '../../env'
|
||||
import { readPushSubscription } from '../../pubsub'
|
||||
import { getNewsletterEmail } from '../../services/newsletters'
|
||||
import { findNewsletterEmail } from '../../services/newsletters'
|
||||
import { saveReceivedEmail } from '../../services/received_emails'
|
||||
import { saveNewsletter } from '../../services/save_newsletter_email'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
|
|
@ -62,7 +62,7 @@ export function emailsServiceRouter() {
|
|||
}
|
||||
|
||||
// get user from newsletter email
|
||||
const newsletterEmail = await getNewsletterEmail(data.to)
|
||||
const newsletterEmail = await findNewsletterEmail(data.to)
|
||||
|
||||
if (!newsletterEmail) {
|
||||
logger.info('newsletter email not found', { email: data.to })
|
||||
|
|
@ -150,7 +150,7 @@ export function emailsServiceRouter() {
|
|||
|
||||
try {
|
||||
// get user from newsletter email
|
||||
const newsletterEmail = await getNewsletterEmail(req.body.to)
|
||||
const newsletterEmail = await findNewsletterEmail(req.body.to)
|
||||
|
||||
if (!newsletterEmail) {
|
||||
logger.info('newsletter email not found', { email: req.body.to })
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import express from 'express'
|
|||
import { SubscriptionStatus } from '../../generated/graphql'
|
||||
import { createPubSubClient, readPushSubscription } from '../../pubsub'
|
||||
import {
|
||||
getNewsletterEmail,
|
||||
findNewsletterEmail,
|
||||
updateConfirmationCode,
|
||||
} from '../../services/newsletters'
|
||||
import { updateReceivedEmail } from '../../services/received_emails'
|
||||
|
|
@ -105,7 +105,7 @@ export function newsletterServiceRouter() {
|
|||
}
|
||||
|
||||
// get user from newsletter email
|
||||
const newsletterEmail = await getNewsletterEmail(data.email)
|
||||
const newsletterEmail = await findNewsletterEmail(data.email)
|
||||
if (!newsletterEmail) {
|
||||
logger.info(`newsletter email not found: ${data.email}`)
|
||||
return res.status(200).send('Not Found')
|
||||
|
|
|
|||
41
packages/api/src/services/api_key.ts
Normal file
41
packages/api/src/services/api_key.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { ApiKey } from '../entity/api_key'
|
||||
import { authTrx } from '../repository'
|
||||
|
||||
export const findApiKeys = async (
|
||||
userId: string,
|
||||
where?: FindOptionsWhere<ApiKey>[] | FindOptionsWhere<ApiKey>,
|
||||
select?: (keyof ApiKey)[]
|
||||
) => {
|
||||
return authTrx(
|
||||
(t) =>
|
||||
t.getRepository(ApiKey).find({
|
||||
select: select || [
|
||||
'id',
|
||||
'name',
|
||||
'scopes',
|
||||
'expiresAt',
|
||||
'createdAt',
|
||||
'usedAt',
|
||||
],
|
||||
where,
|
||||
order: {
|
||||
usedAt: { direction: 'DESC', nulls: 'last' },
|
||||
createdAt: 'DESC',
|
||||
},
|
||||
}),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const deleteApiKey = async (
|
||||
criteria: string[] | FindOptionsWhere<ApiKey>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(ApiKey).delete(criteria),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import * as jwt from 'jsonwebtoken'
|
||||
import { IsNull, Not } from 'typeorm'
|
||||
import { DeepPartial, FindOptionsWhere, IsNull, Not } from 'typeorm'
|
||||
import { Feature } from '../entity/feature'
|
||||
import { env } from '../env'
|
||||
import { authTrx, entityManager } from '../repository'
|
||||
|
|
@ -110,12 +110,49 @@ export const isOptedIn = async (name: FeatureName): Promise<boolean> => {
|
|||
return !!feature
|
||||
}
|
||||
|
||||
export const getFeature = async (
|
||||
name: FeatureName
|
||||
export const findFeatureByName = async (
|
||||
name: FeatureName,
|
||||
userId?: string
|
||||
): Promise<Feature | null> => {
|
||||
return authTrx((t) =>
|
||||
t.getRepository(Feature).findOneBy({
|
||||
name,
|
||||
})
|
||||
return authTrx(
|
||||
(t) =>
|
||||
t.getRepository(Feature).findOneBy({
|
||||
name,
|
||||
}),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const deleteFeature = async (
|
||||
criteria: string[] | FindOptionsWhere<Feature>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
(t) => t.getRepository(Feature).delete(criteria),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const createFeature = async (
|
||||
feature: DeepPartial<Feature>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
(t) => t.getRepository(Feature).save(feature),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const createFeatures = async (
|
||||
features: DeepPartial<Feature>[],
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
(t) => t.getRepository(Feature).save(features),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { ReadwiseIntegration } from './readwise'
|
||||
import { DeepPartial, FindOptionsWhere } from 'typeorm'
|
||||
import { Integration } from '../../entity/integration'
|
||||
import { authTrx } from '../../repository'
|
||||
import { IntegrationService } from './integration'
|
||||
import { PocketIntegration } from './pocket'
|
||||
import { ReadwiseIntegration } from './readwise'
|
||||
|
||||
const integrations: IntegrationService[] = [
|
||||
new ReadwiseIntegration(),
|
||||
|
|
@ -14,3 +17,70 @@ export const getIntegrationService = (name: string): IntegrationService => {
|
|||
}
|
||||
return service
|
||||
}
|
||||
|
||||
export const deleteIntegrations = async (
|
||||
userId: string,
|
||||
criteria: string[] | FindOptionsWhere<Integration>
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).delete(criteria),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const removeIntegration = async (
|
||||
integration: Integration,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).remove(integration),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const findIntegration = async (
|
||||
where: FindOptionsWhere<Integration> | FindOptionsWhere<Integration>[],
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).findOneBy(where),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const findIntegrations = async (
|
||||
userId: string,
|
||||
where?: FindOptionsWhere<Integration> | FindOptionsWhere<Integration>[]
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).find({ where }),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const createIntegration = async (
|
||||
integration: DeepPartial<Integration>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).save(integration),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const updateIntegration = async (
|
||||
id: string,
|
||||
integration: DeepPartial<Integration>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.getRepository(Integration).update(id, integration),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { In } from 'typeorm'
|
||||
import { FindOptionsWhere, In } from 'typeorm'
|
||||
import { EntityLabel } from '../entity/entity_label'
|
||||
import { Label } from '../entity/label'
|
||||
import { createPubSubClient, EntityType } from '../pubsub'
|
||||
|
|
@ -148,3 +148,27 @@ export const findLabelsByIds = async (ids: string[]): Promise<Label[]> => {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
export const createLabel = async (
|
||||
name: string,
|
||||
color: string,
|
||||
userId: string
|
||||
): Promise<Label> => {
|
||||
return authTrx(
|
||||
(t) =>
|
||||
t.withRepository(labelRepository).createLabel({ name, color }, userId),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const deleteLabels = async (
|
||||
criteria: string[] | FindOptionsWhere<Label>,
|
||||
userId: string
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => t.withRepository(labelRepository).delete(criteria),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,15 +355,19 @@ export const updateLibraryItem = async (
|
|||
userId: string,
|
||||
pubsub = createPubSubClient()
|
||||
): Promise<LibraryItem> => {
|
||||
const updatedLibraryItem = await authTrx(async (tx) => {
|
||||
const itemRepo = tx.withRepository(libraryItemRepository)
|
||||
await itemRepo.update(
|
||||
id,
|
||||
libraryItem as QueryDeepPartialEntity<LibraryItem>
|
||||
)
|
||||
const updatedLibraryItem = await authTrx(
|
||||
async (tx) => {
|
||||
const itemRepo = tx.withRepository(libraryItemRepository)
|
||||
await itemRepo.update(
|
||||
id,
|
||||
libraryItem as QueryDeepPartialEntity<LibraryItem>
|
||||
)
|
||||
|
||||
return itemRepo.findOneByOrFail({ id })
|
||||
})
|
||||
return itemRepo.findOneByOrFail({ id })
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
|
||||
await pubsub.entityUpdated<DeepPartial<LibraryItem>>(
|
||||
EntityType.PAGE,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ const parsedAddress = (emailAddress: string): string | undefined => {
|
|||
}
|
||||
|
||||
export const createNewsletterEmail = async (
|
||||
userId: string
|
||||
userId: string,
|
||||
confirmationCode?: string
|
||||
): Promise<NewsletterEmail> => {
|
||||
const user = await userRepository.findOne({
|
||||
where: { id: userId },
|
||||
|
|
@ -36,7 +37,8 @@ export const createNewsletterEmail = async (
|
|||
(t) =>
|
||||
t.getRepository(NewsletterEmail).save({
|
||||
address: emailAddress,
|
||||
user: user,
|
||||
user,
|
||||
confirmationCode,
|
||||
}),
|
||||
undefined,
|
||||
userId
|
||||
|
|
@ -92,7 +94,7 @@ export const updateConfirmationCode = async (
|
|||
return !!result.affected
|
||||
}
|
||||
|
||||
export const getNewsletterEmail = async (
|
||||
export const findNewsletterEmail = async (
|
||||
emailAddress: string
|
||||
): Promise<NewsletterEmail | null> => {
|
||||
const address = parsedAddress(emailAddress)
|
||||
|
|
@ -119,3 +121,14 @@ const createRandomEmailAddress = (userName: string, length: number): string => {
|
|||
*/
|
||||
return `${userName}-${nanoid(length)}e@${inbox}.omnivore.app`
|
||||
}
|
||||
|
||||
export const getNewsletterEmailById = async (
|
||||
id: string,
|
||||
userId: string
|
||||
): Promise<NewsletterEmail | null> => {
|
||||
return authTrx(
|
||||
(t) => t.getRepository(NewsletterEmail).findOneBy({ id }),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
|
|||
7
packages/api/src/services/profile.ts
Normal file
7
packages/api/src/services/profile.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { Profile } from '../entity/profile'
|
||||
import { User } from '../entity/user'
|
||||
import { getRepository } from '../repository'
|
||||
|
||||
export const findProfile = async (user: User): Promise<Profile | null> => {
|
||||
return getRepository(Profile).findOneBy({ user: { id: user.id } })
|
||||
}
|
||||
|
|
@ -181,3 +181,22 @@ export const unsubscribeAll = async (
|
|||
logger.info('Failed to unsubscribe all', error)
|
||||
}
|
||||
}
|
||||
|
||||
export const createSubscription = async (
|
||||
userId: string,
|
||||
name: string,
|
||||
newsletterEmail?: NewsletterEmail,
|
||||
status = SubscriptionStatus.Active,
|
||||
unsubscribeMailTo?: string,
|
||||
subscriptionType = SubscriptionType.Newsletter
|
||||
): Promise<Subscription> => {
|
||||
return getRepository(Subscription).save({
|
||||
user: { id: userId },
|
||||
name,
|
||||
newsletterEmail,
|
||||
status,
|
||||
unsubscribeMailTo,
|
||||
lastFetchedAt: new Date(),
|
||||
type: subscriptionType,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
25
packages/api/src/services/user.ts
Normal file
25
packages/api/src/services/user.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { User } from '../entity/user'
|
||||
import { authTrx } from '../repository'
|
||||
import { userRepository } from '../repository/user'
|
||||
|
||||
export const deleteUser = async (userId: string) => {
|
||||
await authTrx(
|
||||
async (t) => {
|
||||
await t.withRepository(userRepository).delete(userId)
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const updateUser = async (userId: string, update: Partial<User>) => {
|
||||
await authTrx(
|
||||
async (t) => t.getRepository(User).update(userId, update),
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const findUser = async (id: string): Promise<User | null> => {
|
||||
return userRepository.findOneBy({ id })
|
||||
}
|
||||
|
|
@ -1,21 +1,22 @@
|
|||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { UserDeviceToken } from '../entity/user_device_tokens'
|
||||
import { env } from '../env'
|
||||
import { authTrx } from '../repository'
|
||||
import { analytics } from '../utils/analytics'
|
||||
|
||||
export const getDeviceToken = async (
|
||||
export const findDeviceTokenById = async (
|
||||
id: string
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return authTrx((t) => t.getRepository(UserDeviceToken).findOneBy({ id }))
|
||||
}
|
||||
|
||||
export const getDeviceTokenByToken = async (
|
||||
export const findDeviceTokenByToken = async (
|
||||
token: string
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return authTrx((t) => t.getRepository(UserDeviceToken).findOneBy({ token }))
|
||||
}
|
||||
|
||||
export const getDeviceTokensByUserId = async (
|
||||
export const findDeviceTokensByUserId = async (
|
||||
userId: string
|
||||
): Promise<UserDeviceToken[]> => {
|
||||
return authTrx((t) =>
|
||||
|
|
@ -63,3 +64,16 @@ export const deleteDeviceToken = async (
|
|||
return !!result.affected
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteDeviceTokens = async (
|
||||
userId: string,
|
||||
criteria: string[] | FindOptionsWhere<UserDeviceToken>
|
||||
) => {
|
||||
return authTrx(
|
||||
async (t) => {
|
||||
await t.getRepository(UserDeviceToken).delete(criteria)
|
||||
},
|
||||
undefined,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
|
|||
27
packages/api/src/services/webhook.ts
Normal file
27
packages/api/src/services/webhook.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { DeepPartial, EntityManager } from 'typeorm'
|
||||
import { Webhook } from '../entity/webhook'
|
||||
import { authTrx } from '../repository'
|
||||
|
||||
export const createWebhooks = async (
|
||||
webhooks: DeepPartial<Webhook>[],
|
||||
userId?: string,
|
||||
entityManager?: EntityManager
|
||||
) => {
|
||||
return authTrx(
|
||||
(tx) => tx.getRepository(Webhook).save(webhooks),
|
||||
entityManager,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
||||
export const createWebhook = async (
|
||||
webhook: DeepPartial<Webhook>,
|
||||
userId?: string,
|
||||
entityManager?: EntityManager
|
||||
) => {
|
||||
return authTrx(
|
||||
(tx) => tx.getRepository(Webhook).save(webhook),
|
||||
entityManager,
|
||||
userId
|
||||
)
|
||||
}
|
||||
|
|
@ -1,20 +1,18 @@
|
|||
import Postgrator from 'postgrator'
|
||||
import { FindOptionsWhere } from 'typeorm'
|
||||
import { DeepPartial } from 'typeorm'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
import { appDataSource } from '../src/data_source'
|
||||
import { Integration } from '../src/entity/integration'
|
||||
import { Label } from '../src/entity/label'
|
||||
import { NewsletterEmail } from '../src/entity/newsletter_email'
|
||||
import { Profile } from '../src/entity/profile'
|
||||
import { LibraryItem } from '../src/entity/library_item'
|
||||
import { Reminder } from '../src/entity/reminder'
|
||||
import { Subscription } from '../src/entity/subscription'
|
||||
import { User } from '../src/entity/user'
|
||||
import { UserDeviceToken } from '../src/entity/user_device_tokens'
|
||||
import { SubscriptionStatus, SubscriptionType } from '../src/generated/graphql'
|
||||
import { getRepository, setClaims } from '../src/repository'
|
||||
import { getRepository } from '../src/repository'
|
||||
import { userRepository } from '../src/repository/user'
|
||||
import { createUser } from '../src/services/create_user'
|
||||
import { Filter } from "../src/entity/filter"
|
||||
import { createLibraryItem } from '../src/services/library_item'
|
||||
import { createDeviceToken } from '../src/services/user_device_tokens'
|
||||
|
||||
const runMigrations = async () => {
|
||||
const migrationDirectory = __dirname + '/../../db/migrations'
|
||||
|
|
@ -63,13 +61,6 @@ export const createTestConnection = async (): Promise<void> => {
|
|||
await appDataSource.initialize()
|
||||
}
|
||||
|
||||
export const deleteTestUser = async (userId: string) => {
|
||||
await appDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(User).delete(userId)
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteFiltersFromUser = async (userId: string) => {
|
||||
await AppDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
|
|
@ -105,7 +96,7 @@ export const createTestUser = async (
|
|||
}
|
||||
|
||||
export const createUserWithoutProfile = async (name: string): Promise<User> => {
|
||||
return getRepository(User).save({
|
||||
return userRepository.save({
|
||||
source: 'GOOGLE',
|
||||
sourceUserId: 'fake-user-id-' + name,
|
||||
email: `${name}@omnivore.app`,
|
||||
|
|
@ -113,10 +104,6 @@ export const createUserWithoutProfile = async (name: string): Promise<User> => {
|
|||
})
|
||||
}
|
||||
|
||||
export const getProfile = async (user: User): Promise<Profile | null> => {
|
||||
return getRepository(Profile).findOneBy({ user: { id: user.id } })
|
||||
}
|
||||
|
||||
export const createTestReminder = async (
|
||||
user: User,
|
||||
pageId?: string
|
||||
|
|
@ -132,107 +119,24 @@ export const getReminder = async (id: string): Promise<Reminder | null> => {
|
|||
return getRepository(Reminder).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestNewsletterEmail = async (
|
||||
user: User,
|
||||
emailAddress?: string,
|
||||
confirmationCode?: string
|
||||
): Promise<NewsletterEmail> => {
|
||||
return getRepository(NewsletterEmail).save({
|
||||
user: user,
|
||||
address: emailAddress,
|
||||
confirmationCode: confirmationCode,
|
||||
})
|
||||
}
|
||||
|
||||
export const getNewsletterEmail = async (
|
||||
id: string
|
||||
): Promise<NewsletterEmail | null> => {
|
||||
return getRepository(NewsletterEmail).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestDeviceToken = async (
|
||||
user: User
|
||||
): Promise<UserDeviceToken> => {
|
||||
return getRepository(UserDeviceToken).save({
|
||||
user: user,
|
||||
token: 'Test token',
|
||||
})
|
||||
return createDeviceToken(user.id, 'fake-token')
|
||||
}
|
||||
|
||||
export const getDeviceToken = async (
|
||||
id: string
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return getRepository(UserDeviceToken).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const getUser = async (id: string): Promise<User | null> => {
|
||||
return userRepository.findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestLabel = async (
|
||||
user: User,
|
||||
name: string,
|
||||
color: string
|
||||
): Promise<Label> => {
|
||||
return getRepository(Label).save({
|
||||
user,
|
||||
name,
|
||||
color,
|
||||
})
|
||||
}
|
||||
|
||||
export const createTestSubscription = async (
|
||||
user: User,
|
||||
name: string,
|
||||
newsletterEmail?: NewsletterEmail,
|
||||
status = SubscriptionStatus.Active,
|
||||
unsubscribeMailTo?: string,
|
||||
subscriptionType = SubscriptionType.Newsletter
|
||||
): Promise<Subscription> => {
|
||||
return getRepository(Subscription).save({
|
||||
user,
|
||||
name,
|
||||
newsletterEmail,
|
||||
status,
|
||||
unsubscribeMailTo,
|
||||
lastFetchedAt: new Date(),
|
||||
type: subscriptionType,
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteTestLabels = async (
|
||||
export const createTestLibraryItem = async (
|
||||
userId: string,
|
||||
criteria: string[] | FindOptionsWhere<Label>
|
||||
) => {
|
||||
await appDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(Label).delete(criteria)
|
||||
})
|
||||
}
|
||||
labels?: Label[]
|
||||
): Promise<LibraryItem> => {
|
||||
const item: DeepPartial<LibraryItem> = {
|
||||
user: { id: userId },
|
||||
title: 'test title',
|
||||
originalContent: '<p>test content</p>',
|
||||
originalUrl: 'https://blog.omnivore.app/test-url',
|
||||
slug: 'test-with-omnivore',
|
||||
labels,
|
||||
}
|
||||
|
||||
export const deleteTestIntegrations = async (
|
||||
userId: string,
|
||||
criteria: string[] | FindOptionsWhere<Integration>
|
||||
) => {
|
||||
await appDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(Integration).delete(criteria)
|
||||
})
|
||||
}
|
||||
|
||||
export const updateTestUser = async (userId: string, update: Partial<User>) => {
|
||||
await appDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(User).update(userId, update)
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteTestDeviceTokens = async (
|
||||
userId: string,
|
||||
criteria: string[] | FindOptionsWhere<UserDeviceToken>
|
||||
) => {
|
||||
await appDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(UserDeviceToken).delete(criteria)
|
||||
})
|
||||
return createLibraryItem(item, userId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Sanitize Directive', () => {
|
||||
const correctPassword = 'fakePassword'
|
||||
|
|
@ -21,7 +22,7 @@ describe('Sanitize Directive', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Update user with a bio that is too long', () => {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ import { expect } from 'chai'
|
|||
import supertest from 'supertest'
|
||||
import { ApiKey } from '../../src/entity/api_key'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { findApiKeys } from '../../src/services/api_key'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
const testAPIKey = (apiKey: string): supertest.Test => {
|
||||
|
|
@ -44,7 +45,7 @@ describe('Api Key resolver', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('generate api key', () => {
|
||||
|
|
@ -180,10 +181,7 @@ describe('Api Key resolver', () => {
|
|||
}
|
||||
`
|
||||
|
||||
apiKeys = await getRepository(ApiKey).find({
|
||||
select: ['id', 'name'],
|
||||
where: { user: { id: user.id } },
|
||||
})
|
||||
apiKeys = await findApiKeys(user.id, undefined, ['id', 'name'])
|
||||
})
|
||||
|
||||
it('should get api keys', async () => {
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ import {
|
|||
findLibraryItemByUrl,
|
||||
updateLibraryItem
|
||||
} from '../../src/services/library_item'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as createTask from '../../src/utils/createTask'
|
||||
import * as uploads from '../../src/utils/uploads'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import {
|
||||
createTestLibraryItem,
|
||||
generateFakeUuid,
|
||||
graphqlRequest,
|
||||
request
|
||||
|
|
@ -99,47 +99,6 @@ const createArticleQuery = (
|
|||
`
|
||||
}
|
||||
|
||||
const articlesQuery = (after = '') => {
|
||||
return `
|
||||
query {
|
||||
articles(
|
||||
sharedOnly: ${false}
|
||||
after: "${after}"
|
||||
first: 5
|
||||
query: "") {
|
||||
... on ArticlesSuccess {
|
||||
edges {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
url
|
||||
linkId
|
||||
createdAt
|
||||
updatedAt
|
||||
originalArticleUrl
|
||||
labels {
|
||||
id
|
||||
name
|
||||
color
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
... on ArticlesError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
const getArticleQuery = (slug: string) => {
|
||||
return `
|
||||
query {
|
||||
|
|
@ -384,7 +343,7 @@ describe('Article API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('CreateArticle', () => {
|
||||
|
|
@ -570,7 +529,7 @@ describe('Article API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteLibraryItemById(url, user.id)
|
||||
await deleteLibraryItemByUrl(url, user.id)
|
||||
})
|
||||
|
||||
it('it should return that page in the GetArticles Query', async () => {
|
||||
|
|
@ -581,14 +540,14 @@ describe('Article API', () => {
|
|||
|
||||
// Save a link, then archive it
|
||||
let allLinks = await graphqlRequest(
|
||||
articlesQuery(''),
|
||||
searchQuery(''),
|
||||
authToken
|
||||
).expect(200)
|
||||
const justSavedId = allLinks.body.data.articles.edges[0].node.id
|
||||
await archiveLink(authToken, justSavedId)
|
||||
|
||||
// test the negative case, ensuring the archive link wasn't returned
|
||||
allLinks = await graphqlRequest(articlesQuery(''), authToken).expect(
|
||||
allLinks = await graphqlRequest(searchQuery(''), authToken).expect(
|
||||
200
|
||||
)
|
||||
expect(allLinks.body.data.articles.edges[0]?.node?.url).to.not.eq(url)
|
||||
|
|
@ -599,7 +558,7 @@ describe('Article API', () => {
|
|||
authToken
|
||||
).expect(200)
|
||||
|
||||
allLinks = await graphqlRequest(articlesQuery(''), authToken).expect(
|
||||
allLinks = await graphqlRequest(searchQuery(''), authToken).expect(
|
||||
200
|
||||
)
|
||||
expect(allLinks.body.data.articles.edges[0].node.url).to.eq(url)
|
||||
|
|
@ -1201,12 +1160,7 @@ describe('Article API', () => {
|
|||
mutation {
|
||||
setFavoriteArticle(id: "${articleId}") {
|
||||
... on SetFavoriteArticleSuccess {
|
||||
favoriteArticle {
|
||||
id
|
||||
labels {
|
||||
name
|
||||
}
|
||||
}
|
||||
success
|
||||
}
|
||||
... on SetFavoriteArticleError {
|
||||
errorCodes
|
||||
|
|
@ -1234,17 +1188,10 @@ describe('Article API', () => {
|
|||
})
|
||||
|
||||
it('favorites the article', async () => {
|
||||
const res = await graphqlRequest(
|
||||
await graphqlRequest(
|
||||
setFavoriteArticleQuery(articleId),
|
||||
authToken
|
||||
).expect(200)
|
||||
console.log(res.body.data.setFavoriteArticle.favoriteArticle)
|
||||
expect(res.body.data.setFavoriteArticle.favoriteArticle.id).to.eq(
|
||||
articleId
|
||||
)
|
||||
expect(
|
||||
res.body.data.setFavoriteArticle.favoriteArticle.labels[0].name
|
||||
).to.eq('Favorites')
|
||||
|
||||
const item = await findLibraryItemById(articleId, user.id)
|
||||
expect(item?.labels?.map((l) => l.name)).to.eql(['Favorites'])
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ import {
|
|||
CreateArticleSavingRequestErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
import { findLibraryItemByUrl } from '../../src/services/library_item'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as createTask from '../../src/utils/createTask'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
const articleSavingRequestQuery = ({
|
||||
|
|
@ -73,7 +74,7 @@ describe('ArticleSavingRequest API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@ import sinon, { SinonFakeTimers } from 'sinon'
|
|||
import { Feature } from '../../src/entity/feature'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { env } from '../../src/env'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { userRepository } from '../../src/repository/user'
|
||||
import { createFeature, createFeatures, deleteFeature } from '../../src/services/features'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('features resolvers', () => {
|
||||
|
|
@ -24,7 +26,7 @@ describe('features resolvers', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(loginUser.id)
|
||||
await deleteUser(loginUser.id)
|
||||
})
|
||||
|
||||
describe('optInFeature API', () => {
|
||||
|
|
@ -64,9 +66,7 @@ describe('features resolvers', () => {
|
|||
context('when user is the first 1500 users', () => {
|
||||
after(async () => {
|
||||
// reset feature
|
||||
await getRepository(Feature).delete({
|
||||
user: { id: loginUser.id },
|
||||
})
|
||||
await deleteFeature([], loginUser.id)
|
||||
})
|
||||
|
||||
it('opts in to the feature', async () => {
|
||||
|
|
@ -110,7 +110,7 @@ describe('features resolvers', () => {
|
|||
}
|
||||
})
|
||||
|
||||
users = await getRepository(User).save(usersToSave)
|
||||
users = await userRepository.save(usersToSave)
|
||||
|
||||
const features = users.map((user) => {
|
||||
return {
|
||||
|
|
@ -120,16 +120,14 @@ describe('features resolvers', () => {
|
|||
}
|
||||
})
|
||||
|
||||
await getRepository(Feature).save(features)
|
||||
await createFeatures(features, loginUser.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// reset opt-in users
|
||||
Promise.all(users.map((user) => deleteTestUser(user.id)))
|
||||
Promise.all(users.map((user) => deleteUser(user.id)))
|
||||
// reset feature
|
||||
await getRepository(Feature).delete({
|
||||
name: featureName,
|
||||
})
|
||||
await deleteFeature({ name: featureName }, loginUser.id)
|
||||
})
|
||||
|
||||
it('does not opt in to the feature', async () => {
|
||||
|
|
@ -160,18 +158,19 @@ describe('features resolvers', () => {
|
|||
context('when user is already opted in', () => {
|
||||
before(async () => {
|
||||
// opt in
|
||||
await getRepository(Feature).save({
|
||||
user: { id: loginUser.id },
|
||||
name: featureName,
|
||||
grantedAt: new Date(),
|
||||
})
|
||||
await createFeature(
|
||||
{
|
||||
user: { id: loginUser.id },
|
||||
name: featureName,
|
||||
grantedAt: new Date(),
|
||||
},
|
||||
loginUser.id
|
||||
)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// reset feature
|
||||
await getRepository(Feature).delete({
|
||||
user: { id: loginUser.id },
|
||||
})
|
||||
await deleteFeature([], loginUser.id)
|
||||
})
|
||||
|
||||
it('returns the feature', async () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import {
|
||||
createTestLibraryItem,
|
||||
generateFakeUuid,
|
||||
graphqlRequest,
|
||||
request,
|
||||
|
|
@ -10,8 +9,8 @@ import { expect } from 'chai'
|
|||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import chaiString from 'chai-string'
|
||||
import { createPubSubClient } from '../../src/pubsub'
|
||||
import { updateLibraryItem } from '../../src/services/library_item'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
|
|
@ -155,7 +154,7 @@ describe('Highlights API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('createHighlightMutation', () => {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,15 @@ import sinonChai from 'sinon-chai'
|
|||
import { Integration } from '../../src/entity/integration'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { SetIntegrationErrorCode } from '../../src/generated/graphql'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import {
|
||||
createIntegration,
|
||||
deleteIntegrations,
|
||||
findIntegration,
|
||||
updateIntegration,
|
||||
} from '../../src/services/integrations'
|
||||
import { READWISE_API_URL } from '../../src/services/integrations/readwise'
|
||||
import { createTestUser, deleteTestIntegrations, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
|
@ -27,7 +33,7 @@ describe('Integrations resolvers', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(loginUser.id)
|
||||
await deleteUser(loginUser.id)
|
||||
})
|
||||
|
||||
describe('setIntegration API', () => {
|
||||
|
|
@ -110,7 +116,7 @@ describe('Integrations resolvers', () => {
|
|||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteTestIntegrations(loginUser.id, {
|
||||
await deleteIntegrations(loginUser.id, {
|
||||
user: { id: loginUser.id },
|
||||
name: integrationName,
|
||||
})
|
||||
|
|
@ -129,9 +135,9 @@ describe('Integrations resolvers', () => {
|
|||
query(integrationId, integrationName, token),
|
||||
authToken
|
||||
)
|
||||
const integration = await getRepository(Integration).findOneBy({
|
||||
const integration = await findIntegration({
|
||||
id: res.body.data.setIntegration.integration.id,
|
||||
})
|
||||
}, loginUser.id)
|
||||
expect(integration?.taskName).not.to.be.null
|
||||
})
|
||||
})
|
||||
|
|
@ -162,17 +168,17 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
before(async () => {
|
||||
otherUser = await createTestUser('otherUser')
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
existingIntegration = await createIntegration({
|
||||
user: { id: otherUser.id },
|
||||
name: 'READWISE',
|
||||
token: 'fakeToken',
|
||||
})
|
||||
}, otherUser.id)
|
||||
integrationId = existingIntegration.id
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(otherUser.id)
|
||||
await deleteTestIntegrations(otherUser.id, [existingIntegration.id])
|
||||
await deleteUser(otherUser.id)
|
||||
await deleteIntegrations(otherUser.id, [existingIntegration.id])
|
||||
})
|
||||
|
||||
it('returns Unauthorized error code', async () => {
|
||||
|
|
@ -188,16 +194,16 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
context('when integration belongs to the user', () => {
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
existingIntegration = await createIntegration({
|
||||
user: { id: loginUser.id },
|
||||
name: 'READWISE',
|
||||
token: 'fakeToken',
|
||||
})
|
||||
}, loginUser.id)
|
||||
integrationId = existingIntegration.id
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
|
||||
await deleteIntegrations(loginUser.id, [existingIntegration.id])
|
||||
})
|
||||
|
||||
context('when enable is false', () => {
|
||||
|
|
@ -206,10 +212,10 @@ describe('Integrations resolvers', () => {
|
|||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await getRepository(Integration).update(existingIntegration.id, {
|
||||
await updateIntegration(existingIntegration.id, {
|
||||
taskName: 'some task name',
|
||||
enabled: true,
|
||||
})
|
||||
}, loginUser.id)
|
||||
})
|
||||
|
||||
it('disables integration', async () => {
|
||||
|
|
@ -226,9 +232,9 @@ describe('Integrations resolvers', () => {
|
|||
query(integrationId, integrationName, token, enabled),
|
||||
authToken
|
||||
)
|
||||
const integration = await getRepository(Integration).findOneBy({
|
||||
const integration = await findIntegration({
|
||||
id: res.body.data.setIntegration.integration.id,
|
||||
})
|
||||
}, loginUser.id)
|
||||
expect(integration?.taskName).to.be.null
|
||||
})
|
||||
})
|
||||
|
|
@ -239,10 +245,10 @@ describe('Integrations resolvers', () => {
|
|||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await getRepository(Integration).update(existingIntegration.id, {
|
||||
await updateIntegration(existingIntegration.id, {
|
||||
taskName: null,
|
||||
enabled: false,
|
||||
})
|
||||
}, loginUser.id)
|
||||
})
|
||||
|
||||
it('enables integration', async () => {
|
||||
|
|
@ -259,9 +265,9 @@ describe('Integrations resolvers', () => {
|
|||
query(integrationId, integrationName, token, enabled),
|
||||
authToken
|
||||
)
|
||||
const integration = await getRepository(Integration).findOneBy({
|
||||
const integration = await findIntegration({
|
||||
id: res.body.data.setIntegration.integration.id,
|
||||
})
|
||||
}, loginUser.id)
|
||||
expect(integration?.taskName).not.to.be.null
|
||||
})
|
||||
})
|
||||
|
|
@ -288,15 +294,15 @@ describe('Integrations resolvers', () => {
|
|||
let existingIntegration: Integration
|
||||
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
existingIntegration = await createIntegration({
|
||||
user: { id: loginUser.id },
|
||||
name: 'READWISE',
|
||||
token: 'fakeToken',
|
||||
})
|
||||
}, loginUser.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
|
||||
await deleteIntegrations(loginUser.id, [existingIntegration.id])
|
||||
})
|
||||
|
||||
it('returns all integrations', async () => {
|
||||
|
|
@ -334,12 +340,12 @@ describe('Integrations resolvers', () => {
|
|||
let existingIntegration: Integration
|
||||
|
||||
beforeEach(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
existingIntegration = await createIntegration({
|
||||
user: { id: loginUser.id },
|
||||
name: 'READWISE',
|
||||
token: 'fakeToken',
|
||||
taskName: 'some task name',
|
||||
})
|
||||
}, loginUser.id)
|
||||
})
|
||||
|
||||
it('deletes the integration and cloud task', async () => {
|
||||
|
|
@ -347,9 +353,9 @@ describe('Integrations resolvers', () => {
|
|||
query(existingIntegration.id),
|
||||
authToken
|
||||
)
|
||||
const integration = await getRepository(Integration).findOneBy({
|
||||
const integration = await findIntegration({
|
||||
id: existingIntegration.id,
|
||||
})
|
||||
}, loginUser.id)
|
||||
|
||||
expect(res.body.data.deleteIntegration.integration).to.be.an('object')
|
||||
expect(res.body.data.deleteIntegration.integration.id).to.eql(
|
||||
|
|
@ -377,15 +383,15 @@ describe('Integrations resolvers', () => {
|
|||
|
||||
context('when integration exists', () => {
|
||||
before(async () => {
|
||||
existingIntegration = await getRepository(Integration).save({
|
||||
existingIntegration = await createIntegration({
|
||||
user: { id: loginUser.id },
|
||||
name: 'POCKET',
|
||||
token: 'fakeToken',
|
||||
})
|
||||
}, loginUser.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestIntegrations(loginUser.id, [existingIntegration.id])
|
||||
await deleteIntegrations(loginUser.id, [existingIntegration.id])
|
||||
})
|
||||
|
||||
it('returns success and starts cloud task', async () => {
|
||||
|
|
@ -394,9 +400,9 @@ describe('Integrations resolvers', () => {
|
|||
authToken
|
||||
).expect(200)
|
||||
expect(res.body.data.importFromIntegration.success).to.be.true
|
||||
const integration = await getRepository(Integration).findOneBy({
|
||||
const integration = await findIntegration({
|
||||
id: existingIntegration.id,
|
||||
})
|
||||
}, loginUser.id)
|
||||
expect(integration?.taskName).not.to.be.null
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -10,22 +10,14 @@ import {
|
|||
createHighlight,
|
||||
findHighlightById,
|
||||
} from '../../src/services/highlights'
|
||||
import { createLabel, deleteLabels } from '../../src/services/labels'
|
||||
import {
|
||||
deleteLibraryItemById,
|
||||
findLibraryItemById,
|
||||
} from '../../src/services/library_item'
|
||||
import {
|
||||
createTestLabel,
|
||||
createTestUser,
|
||||
deleteTestLabels,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import {
|
||||
createTestLibraryItem,
|
||||
generateFakeUuid,
|
||||
graphqlRequest,
|
||||
request,
|
||||
} from '../util'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Labels API', () => {
|
||||
let user: User
|
||||
|
|
@ -42,7 +34,7 @@ describe('Labels API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('GET labels', () => {
|
||||
|
|
@ -51,16 +43,16 @@ describe('Labels API', () => {
|
|||
|
||||
before(async () => {
|
||||
// create testing labels
|
||||
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
|
||||
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
|
||||
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
|
||||
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
|
||||
labels = [label1, label2]
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestLabels(
|
||||
user.id,
|
||||
labels.map((l) => l.id)
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
user.id
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -151,7 +143,7 @@ describe('Labels API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestLabels(user.id, { name })
|
||||
await deleteLabels({ name }, user.id)
|
||||
})
|
||||
|
||||
it('should create label', async () => {
|
||||
|
|
@ -167,12 +159,12 @@ describe('Labels API', () => {
|
|||
let existingLabel: Label
|
||||
|
||||
before(async () => {
|
||||
existingLabel = await createTestLabel(user, 'label3', '#ffffff')
|
||||
existingLabel = await createLabel(user.id, 'label3', '#ffffff')
|
||||
name = existingLabel.name
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestLabels(user.id, [existingLabel.id])
|
||||
await deleteLabels([existingLabel.id], user.id)
|
||||
})
|
||||
|
||||
it('should return error code LABEL_ALREADY_EXISTS', async () => {
|
||||
|
|
@ -226,8 +218,8 @@ describe('Labels API', () => {
|
|||
|
||||
context('when label is not used', () => {
|
||||
before(async () => {
|
||||
toDeleteLabel = await createTestLabel(
|
||||
user,
|
||||
toDeleteLabel = await createLabel(
|
||||
user.id,
|
||||
'label not in use',
|
||||
'#ffffff'
|
||||
)
|
||||
|
|
@ -245,7 +237,7 @@ describe('Labels API', () => {
|
|||
let item: LibraryItem
|
||||
|
||||
before(async () => {
|
||||
toDeleteLabel = await createTestLabel(user, 'page label', '#ffffff')
|
||||
toDeleteLabel = await createLabel(user.id, 'page label', '#ffffff')
|
||||
labelId = toDeleteLabel.id
|
||||
item = await createTestLibraryItem(user.id, [toDeleteLabel])
|
||||
})
|
||||
|
|
@ -268,8 +260,8 @@ describe('Labels API', () => {
|
|||
|
||||
before(async () => {
|
||||
item = await createTestLibraryItem(user.id)
|
||||
toDeleteLabel = await createTestLabel(
|
||||
user,
|
||||
toDeleteLabel = await createLabel(
|
||||
user.id,
|
||||
'highlight label',
|
||||
'#ffffff'
|
||||
)
|
||||
|
|
@ -334,17 +326,17 @@ describe('Labels API', () => {
|
|||
|
||||
before(async () => {
|
||||
// create testing labels
|
||||
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
|
||||
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
|
||||
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
|
||||
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
|
||||
labels = [label1, label2]
|
||||
item = await createTestLibraryItem(user.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestLabels(
|
||||
user.id,
|
||||
labels.map((l) => l.id)
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
user.id
|
||||
)
|
||||
await deleteLibraryItemById(item.id)
|
||||
})
|
||||
|
|
@ -462,14 +454,14 @@ describe('Labels API', () => {
|
|||
let toUpdateLabel: Label
|
||||
|
||||
before(async () => {
|
||||
toUpdateLabel = await createTestLabel(user, 'label5', '#ffffff')
|
||||
toUpdateLabel = await createLabel(user.id, 'label5', '#ffffff')
|
||||
labelId = toUpdateLabel.id
|
||||
name = 'Updated label'
|
||||
color = '#aabbcc'
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestLabels(user.id, [toUpdateLabel.id])
|
||||
await deleteLabels([toUpdateLabel.id], user.id)
|
||||
})
|
||||
|
||||
it('should return the updated label', async () => {
|
||||
|
|
@ -537,17 +529,17 @@ describe('Labels API', () => {
|
|||
|
||||
before(async () => {
|
||||
// create testing labels
|
||||
const label1 = await createTestLabel(user, 'label_1', '#ffffff')
|
||||
const label2 = await createTestLabel(user, 'label_2', '#eeeeee')
|
||||
const label1 = await createLabel(user.id, 'label_1', '#ffffff')
|
||||
const label2 = await createLabel(user.id, 'label_2', '#eeeeee')
|
||||
labels = [label1, label2]
|
||||
item = await createTestLibraryItem(user.id)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestLabels(
|
||||
user.id,
|
||||
labels.map((l) => l.id)
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
user.id
|
||||
)
|
||||
await deleteLibraryItemById(item.id)
|
||||
})
|
||||
|
|
@ -665,16 +657,16 @@ describe('Labels API', () => {
|
|||
before(async () => {
|
||||
// create testing labels
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const label = await createTestLabel(user, `label_${i}`, '#ffffff')
|
||||
const label = await createLabel(user.id, `label_${i}`, '#ffffff')
|
||||
labels.push(label)
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestLabels(
|
||||
user.id,
|
||||
labels.map((l) => l.id)
|
||||
await deleteLabels(
|
||||
labels.map((l) => l.id),
|
||||
user.id
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ import {
|
|||
} from '../../src/generated/graphql'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import {
|
||||
createTestNewsletterEmail,
|
||||
createTestSubscription,
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
getNewsletterEmail,
|
||||
} from '../db'
|
||||
createNewsletterEmail,
|
||||
findNewsletterEmail,
|
||||
} from '../../src/services/newsletters'
|
||||
import { createSubscription } from '../../src/services/subscriptions'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Newsletters API', () => {
|
||||
|
|
@ -32,7 +32,7 @@ describe('Newsletters API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Get newsletter emails', () => {
|
||||
|
|
@ -61,18 +61,18 @@ describe('Newsletters API', () => {
|
|||
|
||||
before(async () => {
|
||||
// create test newsletter emails
|
||||
const newsletterEmail1 = await createTestNewsletterEmail(
|
||||
user,
|
||||
const newsletterEmail1 = await createNewsletterEmail(
|
||||
user.id,
|
||||
'Test_email_address_1@omnivore.app'
|
||||
)
|
||||
const newsletterEmail2 = await createTestNewsletterEmail(
|
||||
user,
|
||||
const newsletterEmail2 = await createNewsletterEmail(
|
||||
user.id,
|
||||
'Test_email_address_2@omnivore.app'
|
||||
)
|
||||
newsletterEmails = [newsletterEmail1, newsletterEmail2]
|
||||
|
||||
// create testing subscriptions
|
||||
await createTestSubscription(user, 'sub', newsletterEmail2)
|
||||
await createSubscription(user.id, 'sub', newsletterEmail2)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
|
|
@ -118,14 +118,14 @@ describe('Newsletters API', () => {
|
|||
|
||||
before(async () => {
|
||||
// create test newsletter emails
|
||||
newsletterEmail = await createTestNewsletterEmail(
|
||||
user,
|
||||
newsletterEmail = await createNewsletterEmail(
|
||||
user.id,
|
||||
'Test_email_address_1@omnivore.app'
|
||||
)
|
||||
|
||||
// create unsubscribed subscriptions
|
||||
await createTestSubscription(
|
||||
user,
|
||||
await createSubscription(
|
||||
user.id,
|
||||
'sub',
|
||||
newsletterEmail,
|
||||
SubscriptionStatus.Unsubscribed
|
||||
|
|
@ -181,7 +181,7 @@ describe('Newsletters API', () => {
|
|||
|
||||
it('responds with status code 200', async () => {
|
||||
const response = await graphqlRequest(query, authToken).expect(200)
|
||||
const newsletterEmail = await getNewsletterEmail(
|
||||
const newsletterEmail = await findNewsletterEmail(
|
||||
response.body.data.createNewsletterEmail.id
|
||||
)
|
||||
expect(newsletterEmail).not.to.be.undefined
|
||||
|
|
@ -227,8 +227,8 @@ describe('Newsletters API', () => {
|
|||
context('when newsletter email exists', () => {
|
||||
before(async () => {
|
||||
// create test newsletter emails
|
||||
const newsletterEmail = await createTestNewsletterEmail(
|
||||
user,
|
||||
const newsletterEmail = await createNewsletterEmail(
|
||||
user.id,
|
||||
'Test_email_address_1@omnivore.app'
|
||||
)
|
||||
newsletterEmailId = newsletterEmail.id
|
||||
|
|
@ -241,7 +241,7 @@ describe('Newsletters API', () => {
|
|||
|
||||
it('responds with status code 200', async () => {
|
||||
const response = await graphqlRequest(query, authToken).expect(200)
|
||||
const newsletterEmail = await getNewsletterEmail(
|
||||
const newsletterEmail = await findNewsletterEmail(
|
||||
response.body.data.deleteNewsletterEmail.newsletterEmail.id
|
||||
)
|
||||
expect(newsletterEmail).to.be.null
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import { expect } from 'chai'
|
|||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { findLibraryItemById } from '../../src/services/library_item'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('PopularReads API', () => {
|
||||
|
|
@ -36,7 +37,7 @@ describe('PopularReads API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('addPopularRead', () => {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import { NewsletterEmail } from '../../src/entity/newsletter_email'
|
|||
import { ReceivedEmail } from '../../src/entity/received_email'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as sendEmail from '../../src/utils/sendEmail'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Recent Emails Resolver', () => {
|
||||
|
|
@ -59,7 +60,7 @@ describe('Recent Emails Resolver', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('recentEmails', () => {
|
||||
|
|
@ -162,8 +163,8 @@ describe('Recent Emails Resolver', () => {
|
|||
user2Auth = res.body.authToken
|
||||
})
|
||||
after(async () => {
|
||||
await deleteTestUser(user2.id)
|
||||
await deleteTestUser(user3.id)
|
||||
await deleteUser(user2.id)
|
||||
await deleteUser(user3.id)
|
||||
})
|
||||
|
||||
before(async () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import 'mocha'
|
|||
import { SearchHistory } from '../../src/entity/search_history'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('recent_searches resolver', () => {
|
||||
|
|
@ -21,7 +22,7 @@ describe('recent_searches resolver', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('recentSearches API', () => {
|
||||
|
|
|
|||
|
|
@ -9,18 +9,14 @@ import {
|
|||
ReminderErrorCode,
|
||||
UpdateReminderErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
import {
|
||||
createTestReminder,
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
getReminder,
|
||||
} from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import {
|
||||
createTestLibraryItem,
|
||||
generateFakeUuid,
|
||||
graphqlRequest,
|
||||
request,
|
||||
} from '../util'
|
||||
createTestReminder,
|
||||
createTestUser,
|
||||
getReminder,
|
||||
} from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
xdescribe('Reminders API', () => {
|
||||
let authToken: string
|
||||
|
|
@ -44,7 +40,7 @@ xdescribe('Reminders API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Get reminder', () => {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import { ContentDisplayReport } from '../../src/entity/reports/content_display_r
|
|||
import { User } from '../../src/entity/user'
|
||||
import { ReportType } from '../../src/generated/graphql'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestLibraryItem, graphqlRequest, request } from '../util'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Report API', () => {
|
||||
let user: User
|
||||
|
|
@ -28,7 +29,7 @@ describe('Report API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('reportItem', () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import 'mocha'
|
|||
import { Rule, RuleAction, RuleActionType } from '../../src/entity/rule'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Rules Resolver', () => {
|
||||
|
|
@ -24,7 +25,7 @@ describe('Rules Resolver', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('set rules', () => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Send Install Instructions API', () => {
|
||||
let authToken: string
|
||||
|
|
@ -19,7 +20,7 @@ describe('Send Install Instructions API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Send install instructions', () => {
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@ import {
|
|||
SubscriptionType,
|
||||
} from '../../src/generated/graphql'
|
||||
import {
|
||||
createSubscription,
|
||||
unsubscribe,
|
||||
UNSUBSCRIBE_EMAIL_TEXT
|
||||
} from '../../src/services/subscriptions'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createNewsletterEmail } from '../../src/services/newsletters'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as sendEmail from '../../src/utils/sendEmail'
|
||||
import { createTestSubscription, createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
|
@ -35,30 +38,21 @@ describe('Subscriptions API', () => {
|
|||
authToken = res.body.authToken
|
||||
|
||||
// create test newsletter subscriptions
|
||||
const newsletterEmail = await authTrx(
|
||||
(t) =>
|
||||
t.getRepository(NewsletterEmail).save({
|
||||
user,
|
||||
address: 'test@inbox.omnivore.app',
|
||||
confirmationCode: 'test',
|
||||
}),
|
||||
undefined,
|
||||
user.id
|
||||
)
|
||||
const newsletterEmail = await createNewsletterEmail(user.id)
|
||||
|
||||
// create testing newsletter subscriptions
|
||||
const sub1 = await createTestSubscription(user, 'sub_1', newsletterEmail)
|
||||
const sub2 = await createTestSubscription(user, 'sub_2', newsletterEmail)
|
||||
const sub1 = await createSubscription(user.id, 'sub_1', newsletterEmail)
|
||||
const sub2 = await createSubscription(user.id, 'sub_2', newsletterEmail)
|
||||
// create a unsubscribed subscription
|
||||
await createTestSubscription(
|
||||
user,
|
||||
await createSubscription(
|
||||
user.id,
|
||||
'sub_3',
|
||||
newsletterEmail,
|
||||
SubscriptionStatus.Unsubscribed
|
||||
)
|
||||
// create an rss feed subscription
|
||||
const sub4 = await createTestSubscription(
|
||||
user,
|
||||
const sub4 = await createSubscription(
|
||||
user.id,
|
||||
'sub_4',
|
||||
undefined,
|
||||
SubscriptionStatus.Active,
|
||||
|
|
@ -70,7 +64,7 @@ describe('Subscriptions API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('GET subscriptions', () => {
|
||||
|
|
@ -313,8 +307,8 @@ describe('Subscriptions API', () => {
|
|||
address: 'test_2@inbox.omnivore.app',
|
||||
confirmationCode: 'test',
|
||||
})
|
||||
const subscription = await createTestSubscription(
|
||||
user,
|
||||
const subscription = await createSubscription(
|
||||
user.id,
|
||||
name,
|
||||
newsletterEmail,
|
||||
SubscriptionStatus.Active,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ import { expect } from 'chai'
|
|||
import 'mocha'
|
||||
import { LibraryItem } from '../../src/entity/library_item'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestLibraryItem, graphqlRequest, request } from '../util'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Update API', () => {
|
||||
let user: User
|
||||
|
|
@ -23,7 +24,7 @@ describe('Update API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('update page', () => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import {
|
|||
deleteLibraryItemById,
|
||||
findLibraryItemById,
|
||||
} from '../../src/services/library_item'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
|
@ -61,7 +62,7 @@ describe('uploadFileRequest API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('UploadFileRequest', () => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import * as chai from 'chai'
|
||||
import { expect } from 'chai'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import chaiString from 'chai-string'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
|
|
@ -43,7 +44,7 @@ describe('uploadImportFile API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('UploadImportFile', () => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { expect } from 'chai'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import {
|
||||
UpdateUserErrorCode,
|
||||
UpdateUserProfileErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { findProfile } from '../../src/services/profile'
|
||||
import { deleteUser, findUser } from '../../src/services/user'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
import 'mocha'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('User API', () => {
|
||||
const correctPassword = 'fakePassword'
|
||||
|
|
@ -33,8 +35,8 @@ describe('User API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteTestUser(anotherUser.id)
|
||||
await deleteUser(user.id)
|
||||
await deleteUser(anotherUser.id)
|
||||
})
|
||||
|
||||
describe('Update user', () => {
|
||||
|
|
@ -96,7 +98,7 @@ describe('User API', () => {
|
|||
|
||||
it('updates user and responds with status code 200', async () => {
|
||||
const response = await graphqlRequest(query, authToken).expect(200)
|
||||
const user = await getUser(response.body.data.updateUser.user.id)
|
||||
const user = await findUser(response.body.data.updateUser.user.id)
|
||||
expect(user?.name).to.eql(name)
|
||||
})
|
||||
})
|
||||
|
|
@ -160,7 +162,7 @@ describe('User API', () => {
|
|||
|
||||
it('updates user profile and responds with 200', async () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
const profile = await getProfile(user)
|
||||
const profile = await findProfile(user)
|
||||
expect(profile?.username).to.eql(newUsername)
|
||||
})
|
||||
})
|
||||
|
|
@ -196,7 +198,7 @@ describe('User API', () => {
|
|||
context('when username exists', () => {
|
||||
before(async () => {
|
||||
userId = user.id
|
||||
const profile = await getProfile(user)
|
||||
const profile = await findProfile(user)
|
||||
newUsername = profile?.username || 'new_username'
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
import * as chai from 'chai'
|
||||
import { expect } from 'chai'
|
||||
|
|
@ -6,6 +6,7 @@ import 'mocha'
|
|||
import { User } from '../../src/entity/user'
|
||||
import chaiString from 'chai-string'
|
||||
import { DeleteAccountErrorCode } from '../../src/generated/graphql'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ describe('the deleteAccount API', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('deleting a user that exists', () => {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,9 @@ import { User } from '../../src/entity/user'
|
|||
import { UserDeviceToken } from '../../src/entity/user_device_tokens'
|
||||
import { SetDeviceTokenErrorCode } from '../../src/generated/graphql'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import {
|
||||
createTestDeviceToken,
|
||||
createTestUser,
|
||||
deleteTestDeviceTokens,
|
||||
deleteTestUser,
|
||||
getDeviceToken,
|
||||
} from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { deleteDeviceTokens, findDeviceTokenById } from '../../src/services/user_device_tokens'
|
||||
import { createTestDeviceToken, createTestUser } from '../db'
|
||||
import { generateFakeUuid, graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Device tokens API', () => {
|
||||
|
|
@ -33,7 +29,7 @@ describe('Device tokens API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Set device token', () => {
|
||||
|
|
@ -67,7 +63,7 @@ describe('Device tokens API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestDeviceTokens(user.id, { user: { id: user.id } })
|
||||
await deleteDeviceTokens(user.id, { user: { id: user.id } })
|
||||
})
|
||||
|
||||
context('when id in input is not null', () => {
|
||||
|
|
@ -79,7 +75,7 @@ describe('Device tokens API', () => {
|
|||
|
||||
it('responds with status code 200 and deletes the token', async () => {
|
||||
const response = await graphqlRequest(query, authToken).expect(200)
|
||||
const deviceToken = await getDeviceToken(
|
||||
const deviceToken = await findDeviceTokenById(
|
||||
response.body.data.setDeviceToken.deviceToken.id
|
||||
)
|
||||
expect(deviceToken).to.be.null
|
||||
|
|
@ -109,7 +105,7 @@ describe('Device tokens API', () => {
|
|||
|
||||
it('responds with status code 200 and creates the token', async () => {
|
||||
const response = await graphqlRequest(query, authToken).expect(200)
|
||||
const deviceToken = await getDeviceToken(
|
||||
const deviceToken = await findDeviceTokenById(
|
||||
response.body.data.setDeviceToken.deviceToken.id
|
||||
)
|
||||
expect(deviceToken).not.to.be.null
|
||||
|
|
@ -175,7 +171,7 @@ describe('Device tokens API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestDeviceTokens(user.id, { token })
|
||||
await deleteDeviceTokens(user.id, { token })
|
||||
})
|
||||
|
||||
it('responds with status code 200 and returns all device tokens', async () => {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ import 'mocha'
|
|||
import { User } from '../../src/entity/user'
|
||||
import { Webhook } from '../../src/entity/webhook'
|
||||
import { WebhookEvent } from '../../src/generated/graphql'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createWebhooks } from '../../src/services/webhook'
|
||||
import { createTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
|
||||
describe('Webhooks API', () => {
|
||||
|
|
@ -21,28 +23,26 @@ describe('Webhooks API', () => {
|
|||
authToken = res.body.authToken
|
||||
|
||||
// create test webhooks
|
||||
await authTrx(
|
||||
(t) =>
|
||||
t.getRepository(Webhook).save([
|
||||
{
|
||||
url: 'http://localhost:3000/webhooks/test',
|
||||
user: { id: user.id },
|
||||
eventTypes: [WebhookEvent.PageCreated],
|
||||
},
|
||||
{
|
||||
url: 'http://localhost:3000/webhooks/test',
|
||||
user: { id: user.id },
|
||||
eventTypes: [WebhookEvent.PageUpdated],
|
||||
},
|
||||
]),
|
||||
undefined,
|
||||
await createWebhooks(
|
||||
[
|
||||
{
|
||||
url: 'http://localhost:3000/webhooks/test',
|
||||
user: { id: user.id },
|
||||
eventTypes: [WebhookEvent.PageCreated],
|
||||
},
|
||||
{
|
||||
url: 'http://localhost:3000/webhooks/test',
|
||||
user: { id: user.id },
|
||||
eventTypes: [WebhookEvent.PageUpdated],
|
||||
},
|
||||
],
|
||||
user.id
|
||||
)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('Get webhook', () => {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { request } from '../util'
|
||||
import { expect } from 'chai'
|
||||
import nock from 'nock'
|
||||
import 'mocha'
|
||||
import { env } from '../../src/env'
|
||||
import { User } from '../../src/entity/user'
|
||||
import nock from 'nock'
|
||||
import sinon from 'sinon'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { env } from '../../src/env'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as createTask from '../../src/utils/createTask'
|
||||
import { createTestUser } from '../db'
|
||||
import { request } from '../util'
|
||||
|
||||
describe('/article/save API', () => {
|
||||
let user: User
|
||||
|
|
@ -29,7 +30,7 @@ describe('/article/save API', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('POST /article/save', () => {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ import { userRepository } from '../../src/repository/user'
|
|||
import { AuthProvider } from '../../src/routers/auth/auth_types'
|
||||
import { createPendingUserToken } from '../../src/routers/auth/jwt_helpers'
|
||||
import { searchLibraryItems } from '../../src/services/library_item'
|
||||
import { deleteUser, updateUser } from '../../src/services/user'
|
||||
import {
|
||||
comparePassword,
|
||||
generateVerificationToken,
|
||||
hashPassword,
|
||||
} from '../../src/utils/auth'
|
||||
import * as util from '../../src/utils/sendEmail'
|
||||
import { createTestUser, deleteTestUser, updateTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { generateFakeUuid, request } from '../util'
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
|
@ -56,7 +57,7 @@ describe('auth router', () => {
|
|||
|
||||
afterEach(async () => {
|
||||
const user = await getRepository(User).findOneBy({ name })
|
||||
await deleteTestUser(user!.id)
|
||||
await deleteUser(user!.id)
|
||||
})
|
||||
|
||||
context('when confirmation email sent', () => {
|
||||
|
|
@ -123,7 +124,7 @@ describe('auth router', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
it('redirects to sign up page with error code USER_EXISTS', async () => {
|
||||
|
|
@ -190,7 +191,7 @@ describe('auth router', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('when email and password are valid', () => {
|
||||
|
|
@ -216,13 +217,13 @@ describe('auth router', () => {
|
|||
|
||||
beforeEach(async () => {
|
||||
fake = sinon.replace(util, 'sendEmail', sinon.fake.resolves(true))
|
||||
await updateTestUser(user.id, { status: StatusType.Pending })
|
||||
await updateUser(user.id, { status: StatusType.Pending })
|
||||
email = user.email
|
||||
password = correctPassword
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await updateTestUser(user.id, { status: StatusType.Active })
|
||||
await updateUser(user.id, { status: StatusType.Active })
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
|
|
@ -254,13 +255,13 @@ describe('auth router', () => {
|
|||
|
||||
context('when user has no password stored in db', async () => {
|
||||
before(async () => {
|
||||
await updateTestUser(user.id, { password: '' })
|
||||
await updateUser(user.id, { password: '' })
|
||||
email = user.email
|
||||
password = user.password!
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await updateTestUser(user.id, { password })
|
||||
await updateUser(user.id, { password })
|
||||
})
|
||||
|
||||
it('redirects with error code WrongSource', async () => {
|
||||
|
|
@ -301,7 +302,7 @@ describe('auth router', () => {
|
|||
|
||||
after(async () => {
|
||||
sinon.restore()
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('when token is valid', () => {
|
||||
|
|
@ -389,14 +390,14 @@ describe('auth router', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('when email is verified', () => {
|
||||
let fake: (msg: MailDataRequired) => Promise<boolean>
|
||||
|
||||
before(async () => {
|
||||
await updateTestUser(user.id, { status: StatusType.Active })
|
||||
await updateUser(user.id, { status: StatusType.Active })
|
||||
})
|
||||
|
||||
context('when reset password email sent', () => {
|
||||
|
|
@ -438,7 +439,7 @@ describe('auth router', () => {
|
|||
|
||||
context('when email is not verified', () => {
|
||||
before(async () => {
|
||||
await updateTestUser(user.id, { status: StatusType.Pending })
|
||||
await updateUser(user.id, { status: StatusType.Pending })
|
||||
})
|
||||
|
||||
it('redirects to email-login page with error code PENDING_VERIFICATION', async () => {
|
||||
|
|
@ -493,7 +494,7 @@ describe('auth router', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
context('when token is valid', () => {
|
||||
|
|
@ -587,7 +588,7 @@ describe('auth router', () => {
|
|||
|
||||
afterEach(async () => {
|
||||
const user = await userRepository.findOneByOrFail({ name })
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
it('adds popular reads to the library', async () => {
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@ import sinon from 'sinon'
|
|||
import { ReceivedEmail } from '../../src/entity/received_email'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createNewsletterEmail } from '../../src/services/newsletters'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as parser from '../../src/utils/parser'
|
||||
import * as sendEmail from '../../src/utils/sendEmail'
|
||||
import * as sendNotification from '../../src/utils/sendNotification'
|
||||
import {
|
||||
createTestNewsletterEmail,
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { request } from '../util'
|
||||
|
||||
describe('Emails Router', () => {
|
||||
|
|
@ -30,7 +28,7 @@ describe('Emails Router', () => {
|
|||
// create test user and login
|
||||
user = await createTestUser('fakeUser')
|
||||
|
||||
await createTestNewsletterEmail(user, newsletterEmail)
|
||||
await createNewsletterEmail(user.id, newsletterEmail)
|
||||
token = process.env.PUBSUB_VERIFICATION_TOKEN!
|
||||
receivedEmail = await getRepository(ReceivedEmail).save({
|
||||
user: { id: user.id },
|
||||
|
|
@ -45,7 +43,7 @@ describe('Emails Router', () => {
|
|||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,13 @@ import { env } from '../../src/env'
|
|||
import { PubSubRequestBody } from '../../src/pubsub'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { createHighlight, getHighlightUrl } from '../../src/services/highlights'
|
||||
import { deleteIntegrations } from '../../src/services/integrations'
|
||||
import { READWISE_API_URL } from '../../src/services/integrations/readwise'
|
||||
import { deleteLibraryItemById } from '../../src/services/library_item'
|
||||
import { createTestUser, deleteTestIntegrations, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
import { MockBucket } from '../mock_storage'
|
||||
import { createTestLibraryItem, request } from '../util'
|
||||
import { request } from '../util'
|
||||
|
||||
describe('Integrations routers', () => {
|
||||
const baseUrl = '/svc/pubsub/integrations'
|
||||
|
|
@ -35,7 +37,7 @@ describe('Integrations routers', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('sync with integrations', () => {
|
||||
|
|
@ -174,7 +176,7 @@ describe('Integrations routers', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestIntegrations(user.id, [integration.id])
|
||||
await deleteIntegrations(user.id, [integration.id])
|
||||
await deleteLibraryItemById(item.id)
|
||||
})
|
||||
|
||||
|
|
@ -399,7 +401,7 @@ describe('Integrations routers', () => {
|
|||
|
||||
after(async () => {
|
||||
sinon.restore()
|
||||
await deleteTestIntegrations(user.id, [integration.id])
|
||||
await deleteIntegrations(user.id, [integration.id])
|
||||
})
|
||||
|
||||
context('when integration is pocket', () => {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ import * as jwt from 'jsonwebtoken'
|
|||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { findLibraryItemById } from '../../src/services/library_item'
|
||||
import {
|
||||
createTestNewsletterEmail,
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import { createNewsletterEmail } from '../../src/services/newsletters'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
import { request } from '../util'
|
||||
|
||||
describe('PDF attachments Router', () => {
|
||||
|
|
@ -20,13 +18,13 @@ describe('PDF attachments Router', () => {
|
|||
// create test user and login
|
||||
user = await createTestUser('fakeUser')
|
||||
|
||||
await createTestNewsletterEmail(user, newsletterEmail)
|
||||
await createNewsletterEmail(user.id, newsletterEmail)
|
||||
authToken = jwt.sign(newsletterEmail, process.env.JWT_SECRET || '')
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('upload', () => {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@ import 'mocha'
|
|||
import nock from 'nock'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { Webhook } from '../../src/entity/webhook'
|
||||
import { authTrx } from '../../src/repository'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createWebhook } from '../../src/services/webhook'
|
||||
import { createTestUser } from '../db'
|
||||
import { request } from '../util'
|
||||
|
||||
describe('Webhooks Router', () => {
|
||||
|
|
@ -22,21 +23,19 @@ describe('Webhooks Router', () => {
|
|||
.post('/local/debug/fake-user-login')
|
||||
.send({ fakeEmail: user.email })
|
||||
|
||||
webhook = await authTrx(
|
||||
(t) =>
|
||||
t.getRepository(Webhook).save({
|
||||
url: webhookBaseUrl + webhookPath,
|
||||
user: { id: user.id },
|
||||
eventTypes: ['PAGE_CREATED'],
|
||||
}),
|
||||
undefined,
|
||||
webhook = await createWebhook(
|
||||
{
|
||||
url: webhookBaseUrl + webhookPath,
|
||||
user: { id: user.id },
|
||||
eventTypes: ['PAGE_CREATED'],
|
||||
},
|
||||
user.id
|
||||
)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
// clean up
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
describe('trigger webhooks', () => {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import { LibraryItem } from '../../src/entity/library_item'
|
|||
import { ContentDisplayReport } from '../../src/entity/reports/content_display_report'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { ReportType } from '../../src/generated/graphql'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { saveContentDisplayReport } from '../../src/services/reports'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestLibraryItem } from '../util'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestLibraryItem, createTestUser } from '../db'
|
||||
|
||||
chai.use(sinonChai)
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ describe('saveContentDisplayReport', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
it('creates a report', async () => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import sinon from 'sinon'
|
|||
import sinonChai from 'sinon-chai'
|
||||
import { StatusType, User } from '../../src/entity/user'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { createGroup } from '../../src/services/groups'
|
||||
import { findProfile } from '../../src/services/profile'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import * as util from '../../src/utils/sendEmail'
|
||||
import {
|
||||
createTestUser,
|
||||
|
|
@ -75,7 +76,7 @@ describe('create user', () => {
|
|||
const user = await getRepository(User).findOneBy({
|
||||
name: 'userWithoutProfile',
|
||||
})
|
||||
await deleteTestUser(user!.id)
|
||||
await deleteUser(user!.id)
|
||||
})
|
||||
|
||||
const name = 'userWithoutProfile'
|
||||
|
|
@ -83,7 +84,7 @@ describe('create user', () => {
|
|||
|
||||
await createTestUser(user.name)
|
||||
|
||||
const profile = await getProfile(user)
|
||||
const profile = await findProfile(user)
|
||||
|
||||
expect(profile).to.exist
|
||||
})
|
||||
|
|
@ -101,7 +102,7 @@ describe('create user', () => {
|
|||
afterEach(async () => {
|
||||
sinon.restore()
|
||||
const user = await getRepository(User).findOneBy({ name })
|
||||
await deleteTestUser(user!.id)
|
||||
await deleteUser(user!.id)
|
||||
})
|
||||
|
||||
it('creates the user with pending status and correct name', async () => {
|
||||
|
|
@ -126,7 +127,7 @@ describe('create user', () => {
|
|||
after(async () => {
|
||||
sinon.restore()
|
||||
const user = await getRepository(User).findOneBy({ name })
|
||||
await deleteTestUser(user!.id)
|
||||
await deleteUser(user!.id)
|
||||
})
|
||||
|
||||
it('rejects with error', async () => {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@ import 'mocha'
|
|||
import nock from 'nock'
|
||||
import { ReceivedEmail } from '../../src/entity/received_email'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { authTrx } from '../../src/repository'
|
||||
import { findLibraryItemByUrl } from '../../src/services/library_item'
|
||||
import { saveReceivedEmail } from '../../src/services/received_emails'
|
||||
import { saveEmail } from '../../src/services/save_email'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
|
||||
describe('saveEmail', () => {
|
||||
const fakeContent = 'fake content'
|
||||
|
|
@ -22,23 +23,19 @@ describe('saveEmail', () => {
|
|||
.reply(200)
|
||||
.persist()
|
||||
|
||||
receivedEmail = await authTrx(
|
||||
(t) =>
|
||||
t.getRepository(ReceivedEmail).save({
|
||||
user: { id: user.id },
|
||||
from: '',
|
||||
to: '',
|
||||
subject: '',
|
||||
html: '',
|
||||
type: 'non-article',
|
||||
}),
|
||||
undefined,
|
||||
user.id
|
||||
receivedEmail = await saveReceivedEmail(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
user.id,
|
||||
'non-article'
|
||||
)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
scope.persist(false)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,13 @@ import { NewsletterEmail } from '../../src/entity/newsletter_email'
|
|||
import { ReceivedEmail } from '../../src/entity/received_email'
|
||||
import { Subscription } from '../../src/entity/subscription'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { authTrx, getRepository } from '../../src/repository'
|
||||
import { getRepository } from '../../src/repository'
|
||||
import { findLibraryItemByUrl } from '../../src/services/library_item'
|
||||
import { createNewsletterEmail } from '../../src/services/newsletters'
|
||||
import { saveReceivedEmail } from '../../src/services/received_emails'
|
||||
import { saveNewsletter } from '../../src/services/save_newsletter_email'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
import { createTestUser } from '../db'
|
||||
|
||||
describe('saveNewsletterEmail', () => {
|
||||
const fakeContent = 'fake content'
|
||||
|
|
@ -25,24 +27,19 @@ describe('saveNewsletterEmail', () => {
|
|||
before(async () => {
|
||||
user = await createTestUser('fakeUser')
|
||||
newsletterEmail = await createNewsletterEmail(user.id)
|
||||
receivedEmail = await authTrx(
|
||||
(t) =>
|
||||
t.getRepository(ReceivedEmail).save({
|
||||
user: { id: user.id },
|
||||
from,
|
||||
to: newsletterEmail.address,
|
||||
subject: title,
|
||||
text,
|
||||
html: '',
|
||||
type: 'non-article',
|
||||
}),
|
||||
undefined,
|
||||
user.id
|
||||
receivedEmail = await saveReceivedEmail(
|
||||
from,
|
||||
newsletterEmail.address,
|
||||
title,
|
||||
text,
|
||||
'',
|
||||
user.id,
|
||||
'non-article'
|
||||
)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
it('adds the newsletter to the library', async () => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
import supertest from 'supertest'
|
||||
import { DeepPartial } from 'typeorm'
|
||||
import { v4 } from 'uuid'
|
||||
import { Label } from '../src/entity/label'
|
||||
import { LibraryItem } from '../src/entity/library_item'
|
||||
import { createApp } from '../src/server'
|
||||
import { createLibraryItem } from '../src/services/library_item'
|
||||
import { corsConfig } from '../src/utils/corsConfig'
|
||||
|
||||
const { app, apollo } = createApp()
|
||||
|
|
@ -36,19 +32,3 @@ export const graphqlRequest = (
|
|||
export const generateFakeUuid = () => {
|
||||
return v4()
|
||||
}
|
||||
|
||||
export const createTestLibraryItem = async (
|
||||
userId: string,
|
||||
labels?: Label[]
|
||||
): Promise<LibraryItem> => {
|
||||
const item: DeepPartial<LibraryItem> = {
|
||||
user: { id: userId },
|
||||
title: 'test title',
|
||||
originalContent: '<p>test content</p>',
|
||||
originalUrl: 'https://blog.omnivore.app/test-url',
|
||||
slug: 'test-with-omnivore',
|
||||
labels,
|
||||
}
|
||||
|
||||
return createLibraryItem(item, userId)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import {
|
|||
import nock from 'nock'
|
||||
import chaiAsPromised from 'chai-as-promised'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestUser } from '../db'
|
||||
import { deleteUser } from '../../src/services/user'
|
||||
|
||||
chai.use(chaiAsPromised)
|
||||
|
||||
|
|
@ -112,7 +113,7 @@ describe('isProbablyArticle', () => {
|
|||
})
|
||||
|
||||
after(async () => {
|
||||
await deleteTestUser(user.id)
|
||||
await deleteUser(user.id)
|
||||
})
|
||||
|
||||
it('returns true when email is signed up with us', async () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue