import _replace from 'lodash/replace' ; import _some from 'lodash/some' ; import _trim from 'lodash/trim' ; import _uniq from 'lodash/uniq' ; import { ASSET_TYPE , USER_STATE } from 'common/enums' ; import { environment } from 'common/environment' ; import { AssetNotFoundError , AuthenticationError , DuplicateTagError , ForbiddenByStateError , ForbiddenError , NameInvalidError , TagNotFoundError , UserInputError , } from 'common/errors' ; import { fromGlobalId , isValidTagName } from 'common/utils' ; import { MutationToPutTagResolver } from 'definitions' ; const resolver = async ( root , { input : { id , content , cover , description } } , { viewer , dataSources : { systemService , tagService , userService } } ) => { if ( ! viewer . id ) { throw new AuthenticationError ( 'visitor has no permission' ) ; } if ( viewer . state === USER_STATE . frozen ) { throw new ForbiddenByStateError ( `${ viewer . state } user has no permission` ) ; } let coverId ; if ( cover ) { const asset = await systemService . findAssetByUUID ( cover ) ; if ( ! asset || asset . type !== ASSET_TYPE . tagCover || asset . authorId !== viewer . id ) { throw new AssetNotFoundError ( 'tag cover asset does not exists' ) ; } coverId = asset . id ; } else if ( cover === null ) { coverId = null ; } const tagContent = content ? _trim ( content ) : '' ; if ( tagContent && ! isValidTagName ( tagContent ) ) { throw new NameInvalidError ( 'invalid tag name' ) ; } if ( ! id ) { if ( ! tagContent ) { throw new UserInputError ( '"content" is required in creation' ) ; } const tags = await tagService . findByContent ( { content : tagContent } ) ; if ( tags . length > 0 ) { throw new DuplicateTagError ( `dulpicate tag content: ${ tagContent }` ) ; } const newTag = await tagService . create ( { content : tagContent , creator : viewer . id , description , editors : _uniq ( environment . mattyId ? [ environment . mattyId , viewer . id ] : [ viewer . id ] ) , owner : viewer . id , cover : coverId , } ) ; return newTag ; } else { const { id : dbId } = fromGlobalId ( id ) ; const tag = await tagService . baseFindById ( dbId ) ; if ( ! tag ) { throw new TagNotFoundError ( 'tag not found' ) ; } const isOwner = tag . owner === viewer . id ; const isEditor = _some ( tag . editors , ( editor ) => editor === viewer . id ) ; const isMatty = viewer . id === environment . mattyId ; const isMaintainer = isOwner || isEditor || isMatty ; if ( ! isMaintainer ) { throw new ForbiddenError ( 'only owner, editor, and matty can manage tag' ) ; } const updateParams = { } ; if ( tagContent ) { if ( tagContent !== tag . content ) { const tags = await tagService . findByContent ( { content : tagContent } ) ; if ( tags . length > 0 ) { throw new DuplicateTagError ( `dulpicate tag content: ${ tagContent }` ) ; } } updateParams . content = tagContent ; } if ( typeof description !== 'undefined' && description !== null ) { updateParams . description = description ; } if ( typeof coverId !== 'undefined' ) { updateParams . cover = coverId ; } if ( Object . keys ( updateParams ) . length === 0 ) { throw new UserInputError ( 'bad request' ) ; } const updateTag = await tagService . baseUpdate ( dbId , updateParams ) ; await tagService . updateSearch ( { id : updateTag . id , content : updateTag . content , description : updateTag . description , } ) ; if ( tag . cover && tag . cover !== updateTag . cover ) { const coverAsset = await tagService . baseFindById ( tag . cover , 'asset' ) ; if ( coverAsset ) { await systemService . deleteAssetAndAssetMap ( { [ `${ coverAsset . id }` ] : coverAsset . path , } ) ; } } return updateTag ; } } ; export default resolver ;