diff --git a/src/controllers/getUsersLoginStars.js b/src/controllers/getUsersLoginStars.js new file mode 100644 index 00000000..e2b0196c --- /dev/null +++ b/src/controllers/getUsersLoginStars.js @@ -0,0 +1,80 @@ +module.exports = { + docs: { + summary: "List a user's starred packages.", + responses: [ + { + 200: { + description: "Return value is similar to `GET /api/packages`.", + content: {} + } + } + ] + }, + endpoint: { + method: "GET", + paths: [ "/api/users/:login/stars" ], + rateLimit: "generic", + successStatus: 200, + options: { + Allow: "GET", + "X-Content-Type-Options": "nosniff" + } + }, + params: { + login: (context, req) => { return context.query.login(req); } + }, + async logic(params, context) { + const user = await context.database.getUserByName(params.login); + + if (!user.ok) { + const sso = new context.sso(); + + return sso.notOk().addContent(user.content) + .addCalls("db.getUserByName", user); + } + + let pointerCollection = await context.database.getStarredPointersByUserID(user.content.id); + + if (!pointerCollection.ok) { + const sso = new context.sso(); + + return sso.notOk().addContent(pointerCollection.content) + .addCalls("db.getUserByName", user) + .addCalls("db.getStarredPointersByUserID", pointerCollection); + } + + // Since even if the pointerCollection is okay, it could be empty. Meaning the user + // has no stars. This is okay, but getPackageCollectionByID will fail, and result + // in a not found when discovering no packages by the ids passed, which is none. + // So we will catch the exception of pointerCollection being an empty array. + + if ( + Array.isArray(pointerCollection.content) && + pointerCollection.content.length === 0 + ) { + // Check for array to protect from an unexpected return + const sso = new context.sso(); + + return sso.isOk().addContent([]); + } + + let packageCollection = await context.database.getPackageCollectionByID( + pointerCollection.content + ); + + if (!packageCollection.ok) { + const sso = new context.sso(); + + return sso.notOk().addContent(packageCollection.content) + .addCalls("db.getUserByName", user) + .addCalls("db.getStarredPointersByUserID", pointerCollection) + .addCalls("db.getPackageCollectionByID", packageCollection); + } + + packageCollection = await utils.constructPackageObjectShort(packageCollection.content); + + const sso = new context.sso(); + + return sso.isOk().addContent(packageCollection); + } +}; diff --git a/src/controllers/postPackagesPackageNameVersionsVersionNameEventsUninstall.js b/src/controllers/postPackagesPackageNameVersionsVersionNameEventsUninstall.js new file mode 100644 index 00000000..5fac901c --- /dev/null +++ b/src/controllers/postPackagesPackageNameVersionsVersionNameEventsUninstall.js @@ -0,0 +1,38 @@ +module.exports = { + docs: { + summary: "Previously undocumented endpoint. Since v1.0.2 has no effect.", + }, + endpoint: { + method: "POST", + paths: [ + "/api/packages/:packageName/versions/:versionName/events/uninstall", + "/api/themes/:packageName/versions/:versionName/events/uninstall" + ], + rateLimit: "auth", + successStatus: 201, + options: { + Allow: "POST", + "X-Content-Type-Options": "nosniff" + } + }, + params: {}, + async logic(params, context) { + /** + Used when a package is uninstalled, decreases the download count by 1. + Originally an undocumented endpoint. + The decision to return a '201' is based on how other POST endpoints return, + during a successful event. + This endpoint has now been deprecated, as it serves no useful features, + and on further examination may have been intended as a way to collect + data on users, which is not something we implement. + * Deprecated since v1.0.2 + * see: https://github.com/atom/apm/blob/master/src/uninstall.coffee + * While decoupling HTTP handling from logic, the function has been removed + entirely: https://github.com/pulsar-edit/package-backend/pull/171 + */ + + const sso = new context.sso(); + + return sso.isOk().addContent({ ok: true }); + } +} diff --git a/src/setupEndpoints.js b/src/setupEndpoints.js index 59844f7a..0eed61ca 100644 --- a/src/setupEndpoints.js +++ b/src/setupEndpoints.js @@ -10,7 +10,9 @@ const endpoints = [ require("./controllers/getThemesFeatured.js"), require("./controllers/getUpdates.js"), require("./controllers/getUsers.js"), - require("./controllers/getusersLogin.js") + require("./controllers/getusersLogin.js"), + require("./controllers/getUsersLoginStars.js"), + require("./controllers/postPackagesPackageNameVersionsVersionNameEventsUninstall.js") ]; // The CONST Context - Enables access to all other modules within the system @@ -34,7 +36,7 @@ const context = { const genericLimit = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes // Limit each IP per window, 0 disables rate limit - max: process.env.PULSAR_STATUS === "dev" ? 0 : context.config.RATE_LIMIT_GENRIC, + max: process.env.PULSAR_STATUS === "dev" ? 0 : context.config.RATE_LIMIT_GENERIC, standardHeaders: true, // Return rate limit info in headers legacyHeaders: true, // Legacy rate limit info in headers store: new MemoryStore(), // use default memory store