// hive/user.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const fs = require('fs'); const express = require('express'); const mongoose = require('mongoose'); const { SiteController, SiteError } = require('../../../lib/site-lib'); class HiveUserController extends SiteController { constructor (dtp) { super(dtp, module.exports); this.methods = [ { name: 'getResolveUsers', url: '/resolve', params: { 'q': 'string', }, }, { name: 'getUserProfile', url: '/:userId', method: 'GET', }, ]; } async start ( ) { const router = express.Router(); router.use(async (req, res, next) => { res.locals.currentView = 'hive'; return next(); }); router.param('userId', this.populateUserId.bind(this)); router.get('/resolve', this.getResolveUser.bind(this)); router.get('/:userId/picture', this.getUserPicture.bind(this)); router.get('/:userId', this.getUserProfile.bind(this)); router.get('/', this.getCoreUserRoot.bind(this)); return router; } async populateUserId (req, res, next, userId) { const { user: userService } = this.dtp.services; try { userId = mongoose.Types.ObjectId(userId); res.locals.userProfile = await userService.getLocalUserProfile(userId); if (!res.locals.userProfile) { throw new SiteError(404, 'User profile not found'); } res.locals.userProfile = userService.filterUserObject(res.locals.userProfile); res.locals.userProfile.picture.large.imageUri = `/image/${res.locals.userProfile.picture.large._id}`; res.locals.userProfile.picture.small.imageUri = `/image/${res.locals.userProfile.picture.small._id}`; return next(); } catch (error) { this.log.error('failed to provide User profile', { userId, error }); return res.status(error.statusCode || 500).json({ success: false, message: error.message }); } } async getResolveUser (req, res) { const { user: userService } = this.dtp.services; res.locals.hiveView = 'resolve-user'; try { if (!req.query.q || !req.query.q.length) { throw new SiteError(406, 'Must include search term'); } res.locals.q = userService.filterUsername(req.query.q); res.locals.pagination = this.getPaginationParameters(req, 20); res.locals.userProfiles = await userService.searchLocalUserAccounts(res.locals.pagination, res.locals.q); res.locals.userProfiles = res.locals.userProfiles.map((user) => { const apiUser = userService.filterUserObject(user); apiUser.picture.large = `/image/${user.picture.large}`; apiUser.picture.small = `/image/${user.picture.small}`; return apiUser; }); res.status(200).json({ success: true, pagination: res.locals.pagination, count: res.locals.userProfiles.length, params: { q: res.locals.q, }, users: res.locals.userProfiles, }); } catch (error) { this.log.error("failed to resolve user accounts", { error }); res.status(error.statusCode || 500).json({ success: false, message: error.message }); } } async getUserPicture (req, res) { const { hostCache: hostCacheService } = this.dtp.services; const image = res.locals.userProfile.picture[req.query.s || 'small']; res.locals.hiveView = 'user-picture'; if (!image) { return res.status(404).end('Image not found'); } try { const fileInfo = await hostCacheService.getFile(image.file.bucket, image.file.key); const stream = fs.createReadStream(fileInfo.file.path); res.header('Content-Type', image.type); res.header('Content-Length', fileInfo.file.stats.size); res.status(200); stream.pipe(res); } catch (error) { this.log.error('failed to fetch image', { image, error }); return res.status(error.statusCode || 500).json({ success: false, message: error.message, }); } } async getUserProfile (req, res) { res.locals.hiveView = 'user-profile'; res.status(200).json({ success: true, user: res.locals.userProfile, }); } async getCoreUserRoot (req, res) { res.locals.hiveView = 'info'; res.status(200).json({ component: this.component, version: this.dtp.pkg.version, services: this.services, methods: this.methods, }); } } module.exports = { logId: 'ctl:hive:user', index: 'hiveUser', className: 'HiveUserController', create: async (dtp) => { return new HiveUserController(dtp); }, };