mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Async await entity providers (#28841)
* fix: async await entity providers * fix: async await userMembershipGetters * fix: move to export class style for UserMembershipsHandler * fix: update how Publisher model returns its v1 values GitOrigin-RevId: f94bcb81c9703deaf938cdf7dff31c6e24dc4bd8
This commit is contained in:
committed by
Copybot
parent
9b6eab9251
commit
7f3c8a281d
@@ -1,4 +1,4 @@
|
|||||||
import { promisify, callbackify } from 'node:util'
|
import { callbackify } from 'node:util'
|
||||||
import UserGetter from '../User/UserGetter.mjs'
|
import UserGetter from '../User/UserGetter.mjs'
|
||||||
import UserMembershipsHandler from '../UserMembership/UserMembershipsHandler.mjs'
|
import UserMembershipsHandler from '../UserMembership/UserMembershipsHandler.mjs'
|
||||||
import UserMembershipEntityConfigs from '../UserMembership/UserMembershipEntityConfigs.mjs'
|
import UserMembershipEntityConfigs from '../UserMembership/UserMembershipEntityConfigs.mjs'
|
||||||
@@ -55,39 +55,36 @@ async function getCurrentInstitutionsWithLicence(userId) {
|
|||||||
return Object.values(institutions)
|
return Object.values(institutions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getConfirmedAffiliations(userId) {
|
||||||
|
const emailsData = await UserGetter.promises.getUserFullEmails(userId)
|
||||||
|
|
||||||
|
const confirmedAffiliations = emailsData
|
||||||
|
.filter(
|
||||||
|
emailData =>
|
||||||
|
emailData.confirmedAt &&
|
||||||
|
emailData.affiliation &&
|
||||||
|
emailData.affiliation.institution &&
|
||||||
|
emailData.affiliation.institution.confirmed
|
||||||
|
)
|
||||||
|
.map(emailData => emailData.affiliation)
|
||||||
|
|
||||||
|
return confirmedAffiliations
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getManagedInstitutions(userId) {
|
||||||
|
return await UserMembershipsHandler.promises.getEntitiesByUser(
|
||||||
|
UserMembershipEntityConfigs.institution,
|
||||||
|
userId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const InstitutionsGetter = {
|
const InstitutionsGetter = {
|
||||||
getConfirmedAffiliations(userId, callback) {
|
getConfirmedAffiliations: callbackify(getConfirmedAffiliations),
|
||||||
UserGetter.getUserFullEmails(userId, function (error, emailsData) {
|
|
||||||
if (error) {
|
|
||||||
return callback(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
const confirmedAffiliations = emailsData
|
|
||||||
.filter(
|
|
||||||
emailData =>
|
|
||||||
emailData.confirmedAt &&
|
|
||||||
emailData.affiliation &&
|
|
||||||
emailData.affiliation.institution &&
|
|
||||||
emailData.affiliation.institution.confirmed
|
|
||||||
)
|
|
||||||
.map(emailData => emailData.affiliation)
|
|
||||||
|
|
||||||
callback(null, confirmedAffiliations)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
getCurrentInstitutionIds: callbackify(getCurrentInstitutionIds),
|
getCurrentInstitutionIds: callbackify(getCurrentInstitutionIds),
|
||||||
getCurrentInstitutionsWithLicence: callbackify(
|
getCurrentInstitutionsWithLicence: callbackify(
|
||||||
getCurrentInstitutionsWithLicence
|
getCurrentInstitutionsWithLicence
|
||||||
),
|
),
|
||||||
|
getManagedInstitutions: callbackify(getManagedInstitutions),
|
||||||
getManagedInstitutions(userId, callback) {
|
|
||||||
UserMembershipsHandler.getEntitiesByUser(
|
|
||||||
UserMembershipEntityConfigs.institution,
|
|
||||||
userId,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InstitutionsGetter.promises = {
|
InstitutionsGetter.promises = {
|
||||||
@@ -95,7 +92,7 @@ InstitutionsGetter.promises = {
|
|||||||
getCurrentInstitutionIds,
|
getCurrentInstitutionIds,
|
||||||
getCurrentInstitutionsWithLicence,
|
getCurrentInstitutionsWithLicence,
|
||||||
getCurrentAndPastAffiliationIds,
|
getCurrentAndPastAffiliationIds,
|
||||||
getManagedInstitutions: promisify(InstitutionsGetter.getManagedInstitutions),
|
getManagedInstitutions,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InstitutionsGetter
|
export default InstitutionsGetter
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
/* eslint-disable
|
import { callbackifyAll } from '@overleaf/promise-utils'
|
||||||
n/handle-callback-err,
|
|
||||||
max-len,
|
|
||||||
*/
|
|
||||||
// TODO: This file was created by bulk-decaffeinate.
|
|
||||||
// Fix any style issues and re-enable lint.
|
|
||||||
/*
|
|
||||||
* decaffeinate suggestions:
|
|
||||||
* DS207: Consider shorter variations of null checks
|
|
||||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
||||||
*/
|
|
||||||
import async from 'async'
|
|
||||||
|
|
||||||
import { promisifyAll } from '@overleaf/promise-utils'
|
|
||||||
import UserMembershipEntityConfigs from './UserMembershipEntityConfigs.mjs'
|
import UserMembershipEntityConfigs from './UserMembershipEntityConfigs.mjs'
|
||||||
import * as InstitutionModel from '../../models/Institution.mjs'
|
import * as InstitutionModel from '../../models/Institution.mjs'
|
||||||
import * as SubscriptionModel from '../../models/Subscription.mjs'
|
import * as SubscriptionModel from '../../models/Subscription.mjs'
|
||||||
@@ -25,11 +12,25 @@ const EntityModels = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const UserMembershipsHandler = {
|
const UserMembershipsHandler = {
|
||||||
removeUserFromAllEntities(userId, callback) {
|
async getEntitiesByUser(entityConfig, userId) {
|
||||||
// get all writable entity types
|
if (!Features.hasFeature('saas')) {
|
||||||
if (callback == null) {
|
return []
|
||||||
callback = function () {}
|
|
||||||
}
|
}
|
||||||
|
const query = entityConfig.baseQuery || {}
|
||||||
|
query[entityConfig.fields.access] = userId
|
||||||
|
|
||||||
|
const entities =
|
||||||
|
(await EntityModels[entityConfig.modelName].find(query)) || []
|
||||||
|
|
||||||
|
const filledEntities = []
|
||||||
|
for (const entity of entities) {
|
||||||
|
const filled = await entity.fetchV1DataPromise()
|
||||||
|
filledEntities.push(filled)
|
||||||
|
}
|
||||||
|
return filledEntities
|
||||||
|
},
|
||||||
|
|
||||||
|
async removeUserFromAllEntities(userId) {
|
||||||
const entityConfigs = []
|
const entityConfigs = []
|
||||||
for (const key in UserMembershipEntityConfigs) {
|
for (const key in UserMembershipEntityConfigs) {
|
||||||
const entityConfig = UserMembershipEntityConfigs[key]
|
const entityConfig = UserMembershipEntityConfigs[key]
|
||||||
@@ -39,52 +40,19 @@ const UserMembershipsHandler = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove the user from all entities types
|
// remove the user from all entities types
|
||||||
async.map(
|
for (const entityConfig of entityConfigs) {
|
||||||
entityConfigs,
|
await UserMembershipsHandler.removeUserFromEntities(entityConfig, userId)
|
||||||
(entityConfig, innerCallback) =>
|
}
|
||||||
UserMembershipsHandler.removeUserFromEntities(
|
|
||||||
entityConfig,
|
|
||||||
userId,
|
|
||||||
innerCallback
|
|
||||||
),
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
removeUserFromEntities(entityConfig, userId, callback) {
|
async removeUserFromEntities(entityConfig, userId) {
|
||||||
if (callback == null) {
|
|
||||||
callback = function () {}
|
|
||||||
}
|
|
||||||
const removeOperation = { $pull: {} }
|
const removeOperation = { $pull: {} }
|
||||||
removeOperation.$pull[entityConfig.fields.write] = userId
|
removeOperation.$pull[entityConfig.fields.write] = userId
|
||||||
EntityModels[entityConfig.modelName]
|
await EntityModels[entityConfig.modelName].updateMany({}, removeOperation)
|
||||||
.updateMany({}, removeOperation)
|
|
||||||
.then(result => callback(null, result))
|
|
||||||
.catch(callback)
|
|
||||||
},
|
|
||||||
|
|
||||||
getEntitiesByUser(entityConfig, userId, callback) {
|
|
||||||
if (callback == null) {
|
|
||||||
callback = function () {}
|
|
||||||
}
|
|
||||||
if (!Features.hasFeature('saas')) return callback(null, [])
|
|
||||||
const query = Object.assign({}, entityConfig.baseQuery)
|
|
||||||
query[entityConfig.fields.access] = userId
|
|
||||||
EntityModels[entityConfig.modelName]
|
|
||||||
.find(query)
|
|
||||||
.then(entities => {
|
|
||||||
if (entities == null) {
|
|
||||||
entities = []
|
|
||||||
}
|
|
||||||
async.mapSeries(
|
|
||||||
entities,
|
|
||||||
(entity, cb) => entity.fetchV1Data(cb),
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.catch(callback)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
UserMembershipsHandler.promises = promisifyAll(UserMembershipsHandler)
|
export default {
|
||||||
export default UserMembershipsHandler
|
...callbackifyAll(UserMembershipsHandler),
|
||||||
|
promises: UserMembershipsHandler,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import mongoose from '../infrastructure/Mongoose.mjs'
|
import mongoose from '../infrastructure/Mongoose.mjs'
|
||||||
import settings from '@overleaf/settings'
|
import settings from '@overleaf/settings'
|
||||||
import logger from '@overleaf/logger'
|
import logger from '@overleaf/logger'
|
||||||
import { promisify } from '@overleaf/promise-utils'
|
import { callbackify } from '@overleaf/promise-utils'
|
||||||
import { fetchJson } from '@overleaf/fetch-utils'
|
import { fetchJson } from '@overleaf/fetch-utils'
|
||||||
const { Schema } = mongoose
|
const { Schema } = mongoose
|
||||||
const { ObjectId } = Schema
|
const { ObjectId } = Schema
|
||||||
@@ -20,16 +20,15 @@ export const InstitutionSchema = new Schema(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// fetch institution's data from v1 API. Errors are ignored
|
// fetch institution's data from v1 API. Errors are ignored
|
||||||
InstitutionSchema.method('fetchV1Data', async function (callback) {
|
async function fetchV1DataPromise() {
|
||||||
const url = `${settings.apis.v1.url}/universities/list/${this.v1Id}`
|
const url = `${settings.apis.v1.url}/universities/list/${this.v1Id}`
|
||||||
try {
|
try {
|
||||||
const parsedBody = await fetchJson(url)
|
const parsedBody = await fetchJson(url)
|
||||||
this.name = parsedBody != null ? parsedBody.name : undefined
|
this.name = parsedBody?.name
|
||||||
this.countryCode = parsedBody != null ? parsedBody.country_code : undefined
|
this.countryCode = parsedBody?.country_code
|
||||||
this.departments = parsedBody != null ? parsedBody.departments : undefined
|
this.departments = parsedBody?.departments
|
||||||
this.portalSlug = parsedBody != null ? parsedBody.portal_slug : undefined
|
this.portalSlug = parsedBody?.portal_slug
|
||||||
this.enterpriseCommons =
|
this.enterpriseCommons = parsedBody?.enterprise_commons
|
||||||
parsedBody != null ? parsedBody.enterprise_commons : undefined
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// log error and carry on without v1 data
|
// log error and carry on without v1 data
|
||||||
logger.err(
|
logger.err(
|
||||||
@@ -37,12 +36,11 @@ InstitutionSchema.method('fetchV1Data', async function (callback) {
|
|||||||
'[fetchV1DataError]'
|
'[fetchV1DataError]'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
callback(null, this)
|
return this
|
||||||
})
|
}
|
||||||
|
|
||||||
InstitutionSchema.method(
|
InstitutionSchema.method('fetchV1DataPromise', fetchV1DataPromise)
|
||||||
'fetchV1DataPromise',
|
|
||||||
promisify(InstitutionSchema.methods.fetchV1Data)
|
InstitutionSchema.method('fetchV1Data', callbackify(fetchV1DataPromise))
|
||||||
)
|
|
||||||
|
|
||||||
export const Institution = mongoose.model('Institution', InstitutionSchema)
|
export const Institution = mongoose.model('Institution', InstitutionSchema)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import mongoose from '../infrastructure/Mongoose.mjs'
|
import mongoose from '../infrastructure/Mongoose.mjs'
|
||||||
import settings from '@overleaf/settings'
|
import settings from '@overleaf/settings'
|
||||||
import logger from '@overleaf/logger'
|
import logger from '@overleaf/logger'
|
||||||
import request from 'request'
|
import { fetchJson } from '@overleaf/fetch-utils'
|
||||||
|
import { callbackify } from '@overleaf/promise-utils'
|
||||||
const { Schema } = mongoose
|
const { Schema } = mongoose
|
||||||
const { ObjectId } = Schema
|
const { ObjectId } = Schema
|
||||||
|
|
||||||
@@ -13,37 +14,32 @@ export const PublisherSchema = new Schema(
|
|||||||
{ minimize: false }
|
{ minimize: false }
|
||||||
)
|
)
|
||||||
|
|
||||||
// fetch publisher's (brand on v1) data from v1 API. Errors are ignored
|
async function fetchV1DataPromise() {
|
||||||
PublisherSchema.method('fetchV1Data', function (callback) {
|
const url = `${settings.apis.v1.url}/api/v2/brands/${this.slug}`
|
||||||
request(
|
try {
|
||||||
{
|
const parsedBody = await fetchJson(url, {
|
||||||
baseUrl: settings.apis.v1.url,
|
basicAuth: {
|
||||||
url: `/api/v2/brands/${this.slug}`,
|
|
||||||
method: 'GET',
|
|
||||||
auth: {
|
|
||||||
user: settings.apis.v1.user,
|
user: settings.apis.v1.user,
|
||||||
pass: settings.apis.v1.pass,
|
pass: settings.apis.v1.pass,
|
||||||
sendImmediately: true,
|
|
||||||
},
|
},
|
||||||
timeout: settings.apis.v1.timeout,
|
signal: AbortSignal.timeout(settings.apis.v1.timeout),
|
||||||
},
|
})
|
||||||
(error, response, body) => {
|
|
||||||
let parsedBody
|
this.name = parsedBody?.name
|
||||||
try {
|
this.partner = parsedBody?.partner
|
||||||
parsedBody = JSON.parse(body)
|
return this
|
||||||
} catch (error1) {
|
} catch (error) {
|
||||||
// log error and carry on without v1 data
|
// log error and carry on without v1 data
|
||||||
error = error1
|
logger.err(
|
||||||
logger.err(
|
{ model: 'Publisher', slug: this.slug, error },
|
||||||
{ model: 'Publisher', slug: this.slug, error },
|
'[fetchV1DataError]'
|
||||||
'[fetchV1DataError]'
|
)
|
||||||
)
|
}
|
||||||
}
|
return this
|
||||||
this.name = parsedBody != null ? parsedBody.name : undefined
|
}
|
||||||
this.partner = parsedBody != null ? parsedBody.partner : undefined
|
|
||||||
callback(null, this)
|
PublisherSchema.method('fetchV1DataPromise', fetchV1DataPromise)
|
||||||
}
|
|
||||||
)
|
PublisherSchema.method('fetchV1Data', callbackify(fetchV1DataPromise))
|
||||||
})
|
|
||||||
|
|
||||||
export const Publisher = mongoose.model('Publisher', PublisherSchema)
|
export const Publisher = mongoose.model('Publisher', PublisherSchema)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import mongoose from '../infrastructure/Mongoose.mjs'
|
import mongoose from '../infrastructure/Mongoose.mjs'
|
||||||
import { TeamInviteSchema } from './TeamInvite.mjs'
|
import { TeamInviteSchema } from './TeamInvite.mjs'
|
||||||
|
import { callbackify } from '@overleaf/promise-utils'
|
||||||
|
|
||||||
const { Schema } = mongoose
|
const { Schema } = mongoose
|
||||||
const { ObjectId } = Schema
|
const { ObjectId } = Schema
|
||||||
@@ -123,8 +124,11 @@ export const SubscriptionSchema = new Schema(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Subscriptions have no v1 data to fetch
|
// Subscriptions have no v1 data to fetch
|
||||||
SubscriptionSchema.method('fetchV1Data', function (callback) {
|
async function fetchV1DataPromise() {
|
||||||
callback(null, this)
|
return this
|
||||||
})
|
}
|
||||||
|
SubscriptionSchema.method('fetchV1Data', callbackify(fetchV1DataPromise))
|
||||||
|
|
||||||
|
SubscriptionSchema.method('fetchV1DataPromise', fetchV1DataPromise)
|
||||||
|
|
||||||
export const Subscription = mongoose.model('Subscription', SubscriptionSchema)
|
export const Subscription = mongoose.model('Subscription', SubscriptionSchema)
|
||||||
|
|||||||
Reference in New Issue
Block a user