123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import express from 'express'
- import { body, param, query } from 'express-validator'
- import { isProdInstance } from '@server/helpers/core-utils'
- import { isEachUniqueHandleValid, isFollowStateValid, isRemoteHandleValid } from '@server/helpers/custom-validators/follows'
- import { loadActorUrlOrGetFromWebfinger } from '@server/lib/activitypub/actors'
- import { getRemoteNameAndHost } from '@server/lib/activitypub/follow'
- import { getServerActor } from '@server/models/application/application'
- import { MActorFollowActorsDefault } from '@server/types/models'
- import { ServerFollowCreate } from '@shared/models'
- import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
- import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
- import { isEachUniqueHostValid, isHostValid } from '../../helpers/custom-validators/servers'
- import { logger } from '../../helpers/logger'
- import { WEBSERVER } from '../../initializers/constants'
- import { ActorModel } from '../../models/actor/actor'
- import { ActorFollowModel } from '../../models/actor/actor-follow'
- import { areValidationErrors } from './shared'
- const listFollowsValidator = [
- query('state')
- .optional()
- .custom(isFollowStateValid),
- query('actorType')
- .optional()
- .custom(isActorTypeValid),
- (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (areValidationErrors(req, res)) return
- return next()
- }
- ]
- const followValidator = [
- body('hosts')
- .toArray()
- .custom(isEachUniqueHostValid).withMessage('Should have an array of unique hosts'),
- body('handles')
- .toArray()
- .custom(isEachUniqueHandleValid).withMessage('Should have an array of handles'),
- (req: express.Request, res: express.Response, next: express.NextFunction) => {
- // Force https if the administrator wants to follow remote actors
- if (isProdInstance() && WEBSERVER.SCHEME === 'http') {
- return res
- .status(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
- .json({
- error: 'Cannot follow on a non HTTPS web server.'
- })
- }
- if (areValidationErrors(req, res)) return
- const body: ServerFollowCreate = req.body
- if (body.hosts.length === 0 && body.handles.length === 0) {
- return res
- .status(HttpStatusCode.BAD_REQUEST_400)
- .json({
- error: 'You must provide at least one handle or one host.'
- })
- }
- return next()
- }
- ]
- const removeFollowingValidator = [
- param('hostOrHandle')
- .custom(value => isHostValid(value) || isRemoteHandleValid(value)),
- async (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (areValidationErrors(req, res)) return
- const serverActor = await getServerActor()
- const { name, host } = getRemoteNameAndHost(req.params.hostOrHandle)
- const follow = await ActorFollowModel.loadByActorAndTargetNameAndHostForAPI({
- actorId: serverActor.id,
- targetName: name,
- targetHost: host
- })
- if (!follow) {
- return res.fail({
- status: HttpStatusCode.NOT_FOUND_404,
- message: `Follow ${req.params.hostOrHandle} not found.`
- })
- }
- res.locals.follow = follow
- return next()
- }
- ]
- const getFollowerValidator = [
- param('nameWithHost')
- .custom(isValidActorHandle),
- async (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (areValidationErrors(req, res)) return
- let follow: MActorFollowActorsDefault
- try {
- const actorUrl = await loadActorUrlOrGetFromWebfinger(req.params.nameWithHost)
- const actor = await ActorModel.loadByUrl(actorUrl)
- const serverActor = await getServerActor()
- follow = await ActorFollowModel.loadByActorAndTarget(actor.id, serverActor.id)
- } catch (err) {
- logger.warn('Cannot get actor from handle.', { handle: req.params.nameWithHost, err })
- }
- if (!follow) {
- return res.fail({
- status: HttpStatusCode.NOT_FOUND_404,
- message: `Follower ${req.params.nameWithHost} not found.`
- })
- }
- res.locals.follow = follow
- return next()
- }
- ]
- const acceptFollowerValidator = [
- (req: express.Request, res: express.Response, next: express.NextFunction) => {
- const follow = res.locals.follow
- if (follow.state !== 'pending' && follow.state !== 'rejected') {
- return res.fail({ message: 'Follow is not in pending/rejected state.' })
- }
- return next()
- }
- ]
- const rejectFollowerValidator = [
- (req: express.Request, res: express.Response, next: express.NextFunction) => {
- const follow = res.locals.follow
- if (follow.state !== 'pending' && follow.state !== 'accepted') {
- return res.fail({ message: 'Follow is not in pending/accepted state.' })
- }
- return next()
- }
- ]
- // ---------------------------------------------------------------------------
- export {
- followValidator,
- removeFollowingValidator,
- getFollowerValidator,
- acceptFollowerValidator,
- rejectFollowerValidator,
- listFollowsValidator
- }
|