Files
Verso/services/web/test/acceptance/src/mocks/MockV1Api.js
T
Jakob AckermannandCopybot 8523c21158 Merge pull request #16948 from overleaf/jpa-rails-sharelatex-rebranding-step-2
[web] migrate v1 api calls away from ShareLaTeX branded endpoints

GitOrigin-RevId: af08ee029d0cee8f0f171d21b4f2b0b76222b3f8
2024-02-13 09:03:35 +00:00

474 lines
12 KiB
JavaScript

const AbstractMockApi = require('./AbstractMockApi')
const moment = require('moment')
const sinon = require('sinon')
class MockV1Api extends AbstractMockApi {
reset() {
this.affiliations = []
this.allInstitutionDomains = new Set()
this.blocklistedDomains = []
this.brand_variations = {}
this.brands = {}
this.doc_exported = {}
this.docInfo = {}
this.existingEmails = []
this.exportId = null
this.exportParams = null
this.institutionDomains = {}
this.institutionId = 1000
this.institutions = {}
this.syncUserFeatures = sinon.stub()
this.templates = {}
this.updateEmail = sinon.stub()
this.users = {}
this.v1Id = 1000
this.validation_clients = {}
}
nextInstitutionId() {
return this.institutionId++
}
nextV1Id() {
return this.v1Id++
}
setUser(id, user) {
this.users[id] = user
}
getDocInfo(token) {
return this.docInfo[token] || null
}
setDocInfo(token, info) {
this.docInfo[token] = info
}
setExportId(id) {
this.exportId = id
}
getLastExportParams() {
return this.exportParams
}
clearExportParams() {
this.exportParams = null
}
createInstitution(options = {}) {
const id = options.university_id || this.nextInstitutionId()
options.id = id // include ID so that it is included in APIs
this.institutions[id] = { ...options }
if (options && options.hostname) {
this.addInstitutionDomain(id, options.hostname, {
confirmed: options.confirmed,
})
}
return id
}
addInstitutionDomain(institutionId, domain, options = {}) {
if (this.allInstitutionDomains.has(domain)) return
if (!this.institutionDomains[institutionId]) {
this.institutionDomains[institutionId] = {}
}
this.institutionDomains[institutionId][domain] = options
this.allInstitutionDomains.add(domain)
}
updateInstitution(id, options) {
Object.assign(this.institutions[id], options)
}
updateInstitutionDomain(id, domain, options = {}) {
if (!this.institutionDomains[id] || !this.institutionDomains[id][domain])
return
this.institutionDomains[id][domain] = Object.assign(
{},
this.institutionDomains[id][domain],
options
)
}
addAffiliation(userId, email, entitlement, confirmedAt) {
let newAffiliation = true
const institution = {}
if (!email) return
if (!this.affiliations[userId]) this.affiliations[userId] = []
if (
this.affiliations[userId].find(affiliationData => {
return affiliationData.email === email
})
)
newAffiliation = false
if (newAffiliation) {
const domain = email.split('@').pop()
if (this.blocklistedDomains.indexOf(domain.replace('.com', '')) !== -1) {
return
}
if (this.allInstitutionDomains.has(domain)) {
for (const [institutionId, domainData] of Object.entries(
this.institutionDomains
)) {
if (domainData[domain]) {
institution.id = institutionId
}
}
}
if (institution.id) {
this.affiliations[userId].push({ email, institution })
}
}
if (entitlement !== undefined) {
this.affiliations[userId].forEach(affiliation => {
if (affiliation.email === email) {
affiliation.cached_entitlement = entitlement
}
})
}
if (confirmedAt) {
this.affiliations[userId].forEach(affiliation => {
if (affiliation.email === email) {
if (!affiliation.cached_confirmed_at) {
affiliation.cached_confirmed_at = confirmedAt
}
affiliation.cached_reconfirmed_at = confirmedAt
}
})
}
}
setDocExported(token, info) {
this.doc_exported[token] = info
}
setTemplates(templates) {
this.templates = templates
}
applyRoutes() {
this.app.get('/api/v1/overleaf/users/:v1_user_id/plan_code', (req, res) => {
const user = this.users[req.params.v1_user_id]
if (user) {
res.json(user)
} else {
res.sendStatus(404)
}
})
this.app.get(
'/api/v1/overleaf/users/:v1_user_id/subscriptions',
(req, res) => {
const user = this.users[req.params.v1_user_id]
if (user && user.subscription) {
res.json(user.subscription)
} else {
res.sendStatus(404)
}
}
)
this.app.get(
'/api/v1/overleaf/users/:v1_user_id/subscription_status',
(req, res) => {
const user = this.users[req.params.v1_user_id]
if (user && user.subscription_status) {
res.json(user.subscription_status)
} else {
res.sendStatus(404)
}
}
)
this.app.delete(
'/api/v1/overleaf/users/:v1_user_id/subscription',
(req, res) => {
const user = this.users[req.params.v1_user_id]
if (user) {
user.canceled = true
res.sendStatus(200)
} else {
res.sendStatus(404)
}
}
)
this.app.post('/api/v1/overleaf/users/:v1_user_id/sync', (req, res) => {
this.syncUserFeatures(req.params.v1_user_id)
res.sendStatus(200)
})
this.app.post('/api/v1/overleaf/exports', (req, res) => {
this.exportParams = Object.assign({}, req.body)
res.json({ exportId: this.exportId })
})
this.app.get('/api/v2/users/:userId/affiliations', (req, res) => {
if (!this.affiliations[req.params.userId]) return res.json([])
const affiliations = this.affiliations[req.params.userId].map(
affiliation => {
const institutionId = affiliation.institution.id
const domain = affiliation.email.split('@').pop()
const domainData =
this.institutionDomains[institutionId][domain] || {}
const institutionData = this.institutions[institutionId] || {}
affiliation.institution = {
id: institutionId,
name: institutionData.name,
commonsAccount: institutionData.commonsAccount,
isUniversity: !institutionData.institution,
ssoBeta: institutionData.sso_beta || false,
ssoEnabled: institutionData.sso_enabled || false,
maxConfirmationMonths:
institutionData.maxConfirmationMonths || null,
}
affiliation.institution.confirmed = !!domainData.confirmed
affiliation.licence = 'free'
if (
institutionData.commonsAccount &&
(!institutionData.sso_enabled ||
(institutionData.sso_enabled &&
affiliation.cached_entitlement === true))
) {
affiliation.licence = 'pro_plus'
}
if (
institutionData.maxConfirmationMonths &&
affiliation.cached_reconfirmed_at
) {
const lastDayToReconfirm = moment(
affiliation.cached_reconfirmed_at
).add(institutionData.maxConfirmationMonths, 'months')
affiliation.last_day_to_reconfirm = lastDayToReconfirm.toDate()
affiliation.past_reconfirm_date = lastDayToReconfirm.isBefore()
}
return affiliation
}
)
res.json(affiliations)
})
this.app.post('/api/v2/users/:userId/affiliations', (req, res) => {
this.addAffiliation(
req.params.userId,
req.body.email,
req.body.entitlement,
req.body.confirmedAt
)
res.sendStatus(201)
})
this.app.delete('/api/v2/users/:userId/affiliations', (req, res) => {
res.sendStatus(201)
})
this.app.delete('/api/v2/users/:userId/affiliations/:email', (req, res) => {
res.sendStatus(204)
})
this.app.post(
'/api/v2/institutions/reconfirmation_lapsed_processed',
(req, res) => {
res.sendStatus(200)
}
)
this.app.get(
'/api/v2/institutions/need_reconfirmation_lapsed_processed',
(req, res) => {
const usersWithAffiliations = []
Object.keys(this.affiliations).forEach(userId => {
if (this.affiliations[userId].length > 0) {
usersWithAffiliations.push(userId)
}
})
res.json({ data: { users: usersWithAffiliations } })
}
)
this.app.get('/api/v2/brands/:slug', (req, res) => {
let brand
if ((brand = this.brands[req.params.slug])) {
res.json(brand)
} else {
res.sendStatus(404)
}
})
this.app.get('/universities/list', (req, res) => {
const response = []
const university1 = {
id: 1337,
name: 'Institution 1337',
country_code: 'en',
departments: [],
}
const university2 = {
id: 243,
name: 'Institution 243',
country_code: 'en',
departments: [],
}
if (req.query.country_code === 'en') {
response.push(university1)
}
if (req.query.search === 'Institution') {
response.push(university1)
if (req.query.max_results !== '1') {
response.push(university2)
}
}
res.json(response)
})
this.app.get('/universities/list/:id', (req, res) =>
res.json({
id: parseInt(req.params.id),
name: `Institution ${req.params.id}`,
})
)
this.app.get('/university/domains', (req, res) => {
if (req.query.hostname === 'overleaf.com') {
res.json([
{
id: 42,
hostname: 'overleaf.com',
department: 'Overleaf',
confirmed: true,
university: {
id: 1337,
name: 'Institution 1337',
departments: [],
ssoBeta: false,
ssoEnabled: false,
},
},
])
} else {
res.json([])
}
})
this.app.put('/api/v1/overleaf/users/:id/email', (req, res) => {
const { email } = req.body && req.body.user
if (this.existingEmails.includes(email)) {
res.sendStatus(409)
} else {
this.updateEmail(parseInt(req.params.id), email)
res.sendStatus(200)
}
})
this.app.post('/api/v1/overleaf/login', (req, res) => {
for (const id in this.users) {
const user = this.users[id]
if (
user &&
user.email === req.body.email &&
user.password === req.body.password
) {
return res.json({
email: user.email,
valid: true,
user_profile: user.profile,
})
}
}
res.status(403).json({
email: req.body.email,
valid: false,
})
})
this.app.get('/api/v2/partners/:partner/conversions/:id', (req, res) => {
const partner = this.validation_clients[req.params.partner]
const conversion =
partner && partner.conversions && partner.conversions[req.params.id]
if (conversion) {
res.status(200).json({
input_file_uri: conversion,
brand_variation_id: partner.brand_variation_id,
})
} else {
res.status(404).json({})
}
})
this.app.get('/api/v2/brand_variations/:id', (req, res) => {
const variation = this.brand_variations[req.params.id]
if (variation) {
res.status(200).json(variation)
} else {
res.status(404).json({})
}
})
this.app.get('/api/v1/overleaf/docs/:token/is_published', (req, res) => {
return res.json({ allow: true })
})
this.app.get(
'/api/v1/overleaf/users/:user_id/docs/:token/info',
(req, res) => {
const info = this.getDocInfo(req.params.token) || {
exists: false,
exported: false,
}
res.json(info)
}
)
this.app.get('/api/v1/overleaf/docs/:token/info', (req, res) => {
const info = this.getDocInfo(req.params.token) || {
exists: false,
exported: false,
}
res.json(info)
})
this.app.get(
'/api/v1/overleaf/docs/read_token/:token/exists',
(req, res) => {
res.json({ exists: false })
}
)
this.app.get('/api/v2/templates/:templateId', (req, res) => {
const template = this.templates[req.params.templateId]
if (!template) {
return res.sendStatus(404)
}
res.json(template)
})
}
}
module.exports = MockV1Api
// type hint for the inherited `instance` method
/**
* @function instance
* @memberOf MockV1Api
* @static
* @returns {MockV1Api}
*/