2020-10-30 22:18:17 +03:00
|
|
|
import { createNewUser } from '@wasp/core/auth.js'
|
2020-11-17 13:49:10 +03:00
|
|
|
import HttpError from '@wasp/core/HttpError.js'
|
2020-11-24 23:10:26 +03:00
|
|
|
import slug from 'slug'
|
2020-10-30 22:18:17 +03:00
|
|
|
|
|
|
|
export const signup = async ({ username, email, password }, context) => {
|
2020-11-17 13:49:10 +03:00
|
|
|
try {
|
2020-11-24 23:10:26 +03:00
|
|
|
console.log('juhu')
|
2020-11-17 13:49:10 +03:00
|
|
|
await createNewUser({ username, email, password })
|
|
|
|
} catch (err) {
|
|
|
|
// TODO: I wish I didn't have to do this, I would love this to be in some
|
|
|
|
// degree done automatically.
|
|
|
|
if (err.code == 'P2002') {
|
|
|
|
throw new HttpError(400, err.meta.target + " must be unique.")
|
|
|
|
}
|
|
|
|
throw err
|
|
|
|
}
|
2020-10-30 22:18:17 +03:00
|
|
|
}
|
2020-11-19 17:11:23 +03:00
|
|
|
|
|
|
|
export const updateUser = async ({ email, username, bio, profilePictureUrl, newPassword }, context) => {
|
2020-11-20 20:22:49 +03:00
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
2020-11-19 17:11:23 +03:00
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
|
|
|
await context.entities.User.update({
|
2020-11-20 20:22:49 +03:00
|
|
|
where: { id: context.user.id },
|
2020-11-19 17:11:23 +03:00
|
|
|
data: {
|
2020-11-20 20:22:49 +03:00
|
|
|
email,
|
2020-11-19 17:11:23 +03:00
|
|
|
username,
|
|
|
|
bio,
|
|
|
|
profilePictureUrl,
|
2020-11-23 19:31:03 +03:00
|
|
|
// TODO: This is a problem because I save non-hashed password!!!!
|
|
|
|
// We somehow need to make it really hard (or impossible) for user to do this by mistake,
|
|
|
|
// because if even I did it by mistake, it is likely to happen again.
|
|
|
|
// I was used to mongoose doing hashing on save and was not aware it will just save it plain as day.
|
|
|
|
// Actually, is there even a mechanism I can use to change this password?
|
|
|
|
// I don't think so!
|
2020-11-19 17:11:23 +03:00
|
|
|
password: newPassword || undefined
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2020-11-20 20:22:49 +03:00
|
|
|
|
2020-11-25 18:25:26 +03:00
|
|
|
export const createArticle = async ({ title, description, markdownContent, tags }, context) => {
|
2020-11-20 20:22:49 +03:00
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
|
|
|
return await context.entities.Article.create({
|
|
|
|
data: {
|
|
|
|
title,
|
2020-11-24 23:10:26 +03:00
|
|
|
slug: slug(title) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36),
|
2020-11-20 20:22:49 +03:00
|
|
|
description,
|
|
|
|
markdownContent,
|
2020-11-25 18:25:26 +03:00
|
|
|
user: { connect: { id: context.user.id } },
|
|
|
|
tags: { connectOrCreate: tags.map(tag => ({ where: tag, create: tag })) }
|
2020-11-20 20:22:49 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-11-27 00:48:35 +03:00
|
|
|
export const updateArticle = async ({ id, title, description, markdownContent, tags, favorited }, context) => {
|
2020-11-20 20:22:49 +03:00
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
2020-11-26 00:33:48 +03:00
|
|
|
|
|
|
|
const article = await context.entities.Article.findFirst({
|
|
|
|
where: { id, user: { id: context.user.id }}, // TODO: This line is not fun to write.
|
|
|
|
include: { tags: true }
|
|
|
|
})
|
|
|
|
if (!article) {
|
2020-11-25 18:25:26 +03:00
|
|
|
throw new HttpError(404)
|
|
|
|
}
|
|
|
|
|
2020-11-26 00:33:48 +03:00
|
|
|
const subtractTags = (tags1, tags2) => tags1.filter(t1 => !tags2.find(t2 => t2.name === t1.name))
|
|
|
|
const tagsToAdd = tags ? subtractTags(tags, article.tags) : []
|
|
|
|
const tagsToRemove = tags ? subtractTags(article.tags, tags) : []
|
|
|
|
|
2020-11-25 18:25:26 +03:00
|
|
|
await context.entities.Article.update({
|
|
|
|
where: { id },
|
2020-11-20 20:22:49 +03:00
|
|
|
data: {
|
|
|
|
title,
|
|
|
|
description,
|
2020-11-25 18:25:26 +03:00
|
|
|
markdownContent,
|
2020-11-26 00:33:48 +03:00
|
|
|
tags: {
|
|
|
|
connectOrCreate: tagsToAdd.map(tag => ({ where: tag, create: tag })),
|
|
|
|
disconnect: tagsToRemove
|
|
|
|
}
|
2020-11-20 20:22:49 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
export const deleteArticle = async ({ id }, context) => {
|
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
2020-11-27 00:48:35 +03:00
|
|
|
await context.entities.Article.deleteMany({ // TODO: Prisma quirk: I use deleteMany instead of delete so I can specify user.
|
2020-11-20 20:22:49 +03:00
|
|
|
where: { id, user: { id: context.user.id }} // TODO: This line is not fun to write.
|
|
|
|
})
|
|
|
|
}
|
2020-11-25 00:57:14 +03:00
|
|
|
|
2020-11-27 00:48:35 +03:00
|
|
|
export const setArticleFavorited = async ({ id, favorited }, context) => {
|
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
await context.entities.Article.update({
|
|
|
|
where: { id },
|
|
|
|
data: {
|
|
|
|
favoritedBy: {
|
|
|
|
...(favorited === true ? { connect: { username: context.user.username } } :
|
|
|
|
favorited === false ? { disconnect: { username: context.user.username } } :
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-11-25 00:57:14 +03:00
|
|
|
export const createComment = async ({ articleId, content }, context) => {
|
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
|
|
|
return await context.entities.Comment.create({
|
|
|
|
data: {
|
|
|
|
content,
|
|
|
|
user: { connect: { id: context.user.id } },
|
|
|
|
article: { connect: { id: articleId } }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
export const deleteComment = async ({ id }, context) => {
|
|
|
|
if (!context.user) { throw new HttpError(403) }
|
|
|
|
|
|
|
|
// TODO: Nicer error handling! Right now everything is returned as 500 while it could be instead
|
|
|
|
// useful error message about username being taken / not unique, and other validation errors.
|
2020-11-27 00:48:35 +03:00
|
|
|
await context.entities.Comment.deleteMany({ // TODO: Prisma quirk: I use deleteMany instead of delete so I can specify user.
|
2020-11-25 00:57:14 +03:00
|
|
|
where: { id, user: { id: context.user.id }} // TODO: This line is not fun to write.
|
|
|
|
})
|
|
|
|
}
|
2020-11-26 18:35:38 +03:00
|
|
|
|
|
|
|
export const getTags = async (_args, context) => {
|
|
|
|
const tags = await context.entities.ArticleTag.findMany()
|
2020-11-27 00:48:35 +03:00
|
|
|
// NOTE: This is expensi
|
2020-11-26 18:35:38 +03:00
|
|
|
// or do some other trick to make it less expensive.
|
|
|
|
for (const tag of tags) {
|
|
|
|
tag.numArticles = await context.entities.Article.count({ where: { tags: { some: { name: tag.name }}}})
|
|
|
|
}
|
|
|
|
return tags
|
|
|
|
}
|