diff --git a/packages/auth/README.md b/packages/auth/README.md
index bbe704026a..4c6a474b5b 100644
--- a/packages/auth/README.md
+++ b/packages/auth/README.md
@@ -1 +1,12 @@
-# Budibase Authentication Library
\ No newline at end of file
+# Budibase Core backend library
+
+This library contains core functionality, like auth and security features
+which are shared between backend services.
+
+#### Note about top level JS files
+For the purposes of being able to do say `require("@budibase/auth/permissions")` we need to
+specify the exports at the top-level of the module.
+
+For these files they should be limited to a single `require` of the file that should
+be exported and then a single `module.exports = ...` to export the file in
+commonJS.
\ No newline at end of file
diff --git a/packages/auth/db.js b/packages/auth/db.js
new file mode 100644
index 0000000000..4b03ec36cc
--- /dev/null
+++ b/packages/auth/db.js
@@ -0,0 +1 @@
+module.exports = require("./src/db/utils")
diff --git a/packages/auth/package.json b/packages/auth/package.json
index 56b904c966..42bc76f3f4 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -11,6 +11,7 @@
"ioredis": "^4.27.1",
"jsonwebtoken": "^8.5.1",
"koa-passport": "^4.1.4",
+ "lodash": "^4.17.21",
"node-fetch": "^2.6.1",
"passport-google-auth": "^1.0.2",
"passport-google-oauth": "^2.0.0",
diff --git a/packages/auth/permissions.js b/packages/auth/permissions.js
new file mode 100644
index 0000000000..42f37c9c7e
--- /dev/null
+++ b/packages/auth/permissions.js
@@ -0,0 +1 @@
+module.exports = require("./src/security/permissions")
diff --git a/packages/auth/redis.js b/packages/auth/redis.js
new file mode 100644
index 0000000000..0a9dc91881
--- /dev/null
+++ b/packages/auth/redis.js
@@ -0,0 +1,4 @@
+module.exports = {
+ Client: require("./src/redis"),
+ utils: require("./src/redis/utils"),
+}
diff --git a/packages/auth/roles.js b/packages/auth/roles.js
new file mode 100644
index 0000000000..158bcdb6b8
--- /dev/null
+++ b/packages/auth/roles.js
@@ -0,0 +1 @@
+module.exports = require("./src/security/roles")
diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js
index 44fe1da2db..87ff10bd46 100644
--- a/packages/auth/src/db/utils.js
+++ b/packages/auth/src/db/utils.js
@@ -21,6 +21,7 @@ const DocumentTypes = {
TEMPLATE: "template",
APP: "app",
APP_DEV: "app_dev",
+ ROLE: "role",
}
exports.DocumentTypes = DocumentTypes
@@ -28,6 +29,29 @@ exports.APP_PREFIX = DocumentTypes.APP + SEPARATOR
exports.APP_DEV_PREFIX = DocumentTypes.APP_DEV + SEPARATOR
exports.SEPARATOR = SEPARATOR
+/**
+ * If creating DB allDocs/query params with only a single top level ID this can be used, this
+ * is usually the case as most of our docs are top level e.g. tables, automations, users and so on.
+ * More complex cases such as link docs and rows which have multiple levels of IDs that their
+ * ID consists of need their own functions to build the allDocs parameters.
+ * @param {string} docType The type of document which input params are being built for, e.g. user,
+ * link, app, table and so on.
+ * @param {string|null} docId The ID of the document minus its type - this is only needed if looking
+ * for a singular document.
+ * @param {object} otherProps Add any other properties onto the request, e.g. include_docs.
+ * @returns {object} Parameters which can then be used with an allDocs request.
+ */
+function getDocParams(docType, docId = null, otherProps = {}) {
+ if (docId == null) {
+ docId = ""
+ }
+ return {
+ ...otherProps,
+ startkey: `${docType}${SEPARATOR}${docId}`,
+ endkey: `${docType}${SEPARATOR}${docId}${UNICODE_MAX}`,
+ }
+}
+
/**
* Generates a new group ID.
* @returns {string} The new group ID which the group doc can be stored under.
@@ -97,6 +121,21 @@ exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => {
}
}
+/**
+ * Generates a new role ID.
+ * @returns {string} The new role ID which the role doc can be stored under.
+ */
+exports.generateRoleID = id => {
+ return `${DocumentTypes.ROLE}${SEPARATOR}${id || newid()}`
+}
+
+/**
+ * Gets parameters for retrieving a role, this is a utility function for the getDocParams function.
+ */
+exports.getRoleParams = (roleId = null, otherProps = {}) => {
+ return getDocParams(DocumentTypes.ROLE, roleId, otherProps)
+}
+
/**
* Generates a new configuration ID.
* @returns {string} The new configuration ID which the config doc can be stored under.
diff --git a/packages/auth/src/objectStore/index.js b/packages/auth/src/objectStore/index.js
index ecd3bd3af6..c6d1c3e2ce 100644
--- a/packages/auth/src/objectStore/index.js
+++ b/packages/auth/src/objectStore/index.js
@@ -126,7 +126,13 @@ exports.makeSureBucketExists = async (client, bucketName) => {
* Uploads the contents of a file given the required parameters, useful when
* temp files in use (for example file uploaded as an attachment).
*/
-exports.upload = async ({ bucket: bucketName, filename, path, type, metadata }) => {
+exports.upload = async ({
+ bucket: bucketName,
+ filename,
+ path,
+ type,
+ metadata,
+}) => {
const extension = [...filename.split(".")].pop()
const fileBytes = fs.readFileSync(path)
diff --git a/packages/server/src/utilities/security/permissions.js b/packages/auth/src/security/permissions.js
similarity index 100%
rename from packages/server/src/utilities/security/permissions.js
rename to packages/auth/src/security/permissions.js
diff --git a/packages/server/src/utilities/security/roles.js b/packages/auth/src/security/roles.js
similarity index 98%
rename from packages/server/src/utilities/security/roles.js
rename to packages/auth/src/security/roles.js
index abfaa5c241..93e1769cf1 100644
--- a/packages/server/src/utilities/security/roles.js
+++ b/packages/auth/src/security/roles.js
@@ -1,7 +1,7 @@
-const CouchDB = require("../../db")
+const { getDB } = require("../db")
const { cloneDeep } = require("lodash/fp")
const { BUILTIN_PERMISSION_IDS, higherPermission } = require("./permissions")
-const { generateRoleID, DocumentTypes, SEPARATOR } = require("../../db/utils")
+const { generateRoleID, DocumentTypes, SEPARATOR } = require("../db/utils")
const BUILTIN_IDS = {
ADMIN: "ADMIN",
@@ -116,7 +116,7 @@ exports.getRole = async (appId, roleId) => {
)
}
try {
- const db = new CouchDB(appId)
+ const db = getDB(appId)
const dbRole = await db.get(exports.getDBRoleID(roleId))
role = Object.assign(role, dbRole)
// finalise the ID
@@ -145,7 +145,7 @@ async function getAllUserRoles(appId, userRoleId) {
currentRole &&
currentRole.inherits &&
roleIds.indexOf(currentRole.inherits) === -1
- ) {
+ ) {
roleIds.push(currentRole.inherits)
currentRole = await exports.getRole(appId, currentRole.inherits)
roles.push(currentRole)
diff --git a/packages/builder/src/components/start/AppCard.svelte b/packages/builder/src/components/start/AppCard.svelte
index 174ac585d4..a4edb756f4 100644
--- a/packages/builder/src/components/start/AppCard.svelte
+++ b/packages/builder/src/components/start/AppCard.svelte
@@ -37,8 +37,8 @@
{#if deletable}
+ Delete
+
{/if}
{#if app.lockedBy && app.lockedBy?.email === $auth.user?.email}