search support for od business

This commit is contained in:
spencerwooo
2022-01-24 16:18:55 +08:00
parent fad501a562
commit bfbe4eb042
4 changed files with 67 additions and 11 deletions
+6 -8
View File
@@ -25,14 +25,12 @@ function useDriveItemSearch() {
// Map parentReference to the absolute path of the search result
data.map(item => {
// TODO: supporting sharepoint search where the path is not returned in parentReference
if ('path' in item.parentReference) {
item['path'] = `${mapAbsolutePath(item.parentReference.path)}/${encodeURIComponent(item.name)}`
} else {
throw Error(
'We currently only support search in OneDrive international. SharePoint instances are not supported yet. See issue: https://github.com/spencerwooo/onedrive-vercel-index/issues/299'
)
}
item['path'] =
'path' in item.parentReference
? // OneDrive International have the path returned in the parentReference field
`${mapAbsolutePath(item.parentReference.path)}/${encodeURIComponent(item.name)}`
: // OneDrive for Business/Education does not, so we need extra steps here
''
})
return data
+11
View File
@@ -12,6 +12,12 @@ import { getOdAuthTokens, storeOdAuthTokens } from '../../utils/odAuthTokenStore
const basePath = pathPosix.resolve('/', siteConfig.baseDirectory)
const clientSecret = revealObfuscatedToken(apiConfig.obfuscatedClientSecret)
/**
* Encode the path of the file relative to the base directory
*
* @param path Relative path of the file to the base directory
* @returns Absolute path of the file inside OneDrive
*/
export function encodePath(path: string): string {
let encodedPath = pathPosix.join(basePath, pathPosix.resolve('/', path))
if (encodedPath === '/' || encodedPath === '') {
@@ -21,6 +27,11 @@ export function encodePath(path: string): string {
return `:${encodeURIComponent(encodedPath)}`
}
/**
* Fetch the access token from Redis storage and check if the token requires a renew
*
* @returns Access token for OneDrive API
*/
export async function getAccessToken(): Promise<string> {
const { accessToken, refreshToken } = await getOdAuthTokens()
+32
View File
@@ -0,0 +1,32 @@
import axios from 'axios'
import type { NextApiRequest, NextApiResponse } from 'next'
import { encodePath, getAccessToken } from '.'
import apiConfig from '../../config/api.json'
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Get access token from storage
const accessToken = await getAccessToken()
// Get item details (specifically, its path) by its unique ID in OneDrive
const { id = '' } = req.query
if (typeof id === 'string') {
const itemApi = `${apiConfig.driveApi}/items/${id}`
try {
const { data } = await axios.get(itemApi, {
headers: { Authorization: `Bearer ${accessToken}` },
params: {
select: 'id,name,parentReference',
},
})
res.status(200).json(data)
} catch (error: any) {
res.status(error.response.status).json({ error: error.response.data })
}
} else {
res.status(400).json({ error: 'Invalid driveItem ID.' })
}
return
}
+18 -3
View File
@@ -3,6 +3,18 @@ import type { NextApiRequest, NextApiResponse } from 'next'
import { encodePath, getAccessToken } from '.'
import apiConfig from '../../config/api.json'
import siteConfig from '../../config/site.json'
/**
* Sanitize the search query
*
* @param query User search query, which may contain special characters
* @returns Sanitised query string which replaces non-alphanumeric characters with ' '
*/
function sanitiseQuery(query: string): string {
const sanitisedQuery = query.replace(/[^a-zA-Z0-9]/g, ' ')
return encodeURIComponent(sanitisedQuery)
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Get access token from storage
@@ -12,15 +24,18 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const { q: searchQuery = '' } = req.query
if (typeof searchQuery === 'string') {
// Construct Microsoft Graph Search API URL, and perform search only under the base dir
const encodedPath = encodePath('/') === '' ? encodePath('/') : encodePath('/') + ':'
const searchApi = `${apiConfig.driveApi}/root${encodedPath}/search(q='${encodeURIComponent(searchQuery)}')`
// Construct Microsoft Graph Search API URL, and perform search only under the base directory
const searchRootPath = encodePath('/')
const encodedPath = searchRootPath === '' ? searchRootPath : searchRootPath + ':'
const searchApi = `${apiConfig.driveApi}/root${encodedPath}/search(q='${sanitiseQuery(searchQuery)}')`
try {
const { data } = await axios.get(searchApi, {
headers: { Authorization: `Bearer ${accessToken}` },
params: {
select: 'id,name,file,folder,parentReference',
top: siteConfig.maxItems,
},
})
res.status(200).json(data.value)