-
diff --git a/packages/server/package.json b/packages/server/package.json
index e4c0e8be32..cb1789c5c9 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -81,6 +81,7 @@
"lodash": "^4.17.13",
"mustache": "^4.0.1",
"node-fetch": "^2.6.0",
+ "open": "^7.3.0",
"pino-pretty": "^4.0.0",
"pouchdb": "^7.2.1",
"pouchdb-all-dbs": "^1.0.2",
diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js
index f124bd2ff9..b1585afbe6 100644
--- a/packages/server/src/api/controllers/application.js
+++ b/packages/server/src/api/controllers/application.js
@@ -31,6 +31,7 @@ const { HOME_SCREEN } = require("../../constants/screens")
const { cloneDeep } = require("lodash/fp")
const { recurseMustache } = require("../../utilities/mustache")
const { generateAssetCss } = require("../../utilities/builder/generateCss")
+const { USERS_TABLE_SCHEMA } = require("../../constants")
const APP_PREFIX = DocumentTypes.APP + SEPARATOR
@@ -85,6 +86,9 @@ async function createInstance(template) {
if (!ok) {
throw "Error loading database dump from template."
}
+ } else {
+ // create the users table
+ await db.put(USERS_TABLE_SCHEMA)
}
return { _id: appId }
diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js
index ccf26b02e2..c7fb70d50e 100644
--- a/packages/server/src/api/controllers/row.js
+++ b/packages/server/src/api/controllers/row.js
@@ -6,7 +6,9 @@ const {
generateRowID,
DocumentTypes,
SEPARATOR,
+ ViewNames,
} = require("../../db/utils")
+const usersController = require("./user")
const { cloneDeep } = require("lodash")
const TABLE_VIEW_BEGINS_WITH = `all${SEPARATOR}${DocumentTypes.TABLE}${SEPARATOR}`
@@ -118,6 +120,16 @@ exports.save = async function(ctx) {
table,
})
+ // Creation of a new user goes to the user controller
+ if (!existingRow && row.tableId === ViewNames.USERS) {
+ try {
+ await usersController.create(ctx)
+ } catch (err) {
+ ctx.body = { errors: [err.message] }
+ }
+ return
+ }
+
if (existingRow) {
const response = await db.put(row)
row._rev = response.rev
@@ -315,8 +327,8 @@ exports.fetchEnrichedRow = async function(ctx) {
ctx.status = 200
}
-function coerceRowValues(rec, table) {
- const row = cloneDeep(rec)
+function coerceRowValues(record, table) {
+ const row = cloneDeep(record)
for (let [key, value] of Object.entries(row)) {
const field = table.schema[key]
if (!field) continue
diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js
index c51e1fd2b8..f67ae72a89 100644
--- a/packages/server/src/api/controllers/user.js
+++ b/packages/server/src/api/controllers/user.js
@@ -1,6 +1,6 @@
const CouchDB = require("../../db")
const bcrypt = require("../../utilities/bcrypt")
-const { generateUserID, getUserParams } = require("../../db/utils")
+const { generateUserID, getUserParams, ViewNames } = require("../../db/utils")
const {
BUILTIN_LEVEL_ID_ARRAY,
} = require("../../utilities/security/accessLevels")
@@ -11,7 +11,7 @@ const {
exports.fetch = async function(ctx) {
const database = new CouchDB(ctx.user.appId)
const data = await database.allDocs(
- getUserParams(null, {
+ getUserParams("", {
include_docs: true,
})
)
@@ -44,6 +44,7 @@ exports.create = async function(ctx) {
type: "user",
accessLevelId,
permissions: permissions || [BUILTIN_PERMISSION_NAMES.POWER],
+ tableId: ViewNames.USERS,
}
try {
diff --git a/packages/server/src/automations/steps/createUser.js b/packages/server/src/automations/steps/createUser.js
index 4b6250ce36..b24c2cbe56 100644
--- a/packages/server/src/automations/steps/createUser.js
+++ b/packages/server/src/automations/steps/createUser.js
@@ -28,7 +28,7 @@ module.exports.definition = {
accessLevelId: {
type: "string",
title: "Access Level",
- enum: accessLevels.BUILTIN_LEVEL_IDS,
+ enum: accessLevels.BUILTIN_LEVEL_ID_ARRAY,
pretty: accessLevels.BUILTIN_LEVEL_NAME_ARRAY,
},
},
diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js
index cae1cde3e8..24fe45eb6b 100644
--- a/packages/server/src/constants/index.js
+++ b/packages/server/src/constants/index.js
@@ -1,7 +1,42 @@
+const { BUILTIN_LEVEL_IDS } = require("../utilities/security/accessLevels")
+
const AuthTypes = {
APP: "app",
BUILDER: "builder",
EXTERNAL: "external",
}
+const USERS_TABLE_SCHEMA = {
+ _id: "ta_users",
+ type: "table",
+ views: {},
+ name: "Users",
+ schema: {
+ username: {
+ type: "string",
+ constraints: {
+ type: "string",
+ length: {
+ maximum: "",
+ },
+ presence: true,
+ },
+ fieldName: "username",
+ name: "username",
+ },
+ accessLevelId: {
+ fieldName: "accessLevelId",
+ name: "accessLevelId",
+ type: "options",
+ constraints: {
+ type: "string",
+ presence: false,
+ inclusion: Object.keys(BUILTIN_LEVEL_IDS),
+ },
+ },
+ },
+ primaryDisplay: "username",
+}
+
exports.AuthTypes = AuthTypes
+exports.USERS_TABLE_SCHEMA = USERS_TABLE_SCHEMA
diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js
index 9d9e470ec1..1de007800a 100644
--- a/packages/server/src/db/utils.js
+++ b/packages/server/src/db/utils.js
@@ -20,6 +20,7 @@ const DocumentTypes = {
const ViewNames = {
LINK: "by_link",
ROUTING: "screen_routes",
+ USERS: "ta_users",
}
exports.ViewNames = ViewNames
@@ -80,13 +81,12 @@ exports.generateTableID = () => {
exports.getRowParams = (tableId = null, rowId = null, otherProps = {}) => {
if (tableId == null) {
return getDocParams(DocumentTypes.ROW, null, otherProps)
- } else {
- const endOfKey =
- rowId == null
- ? `${tableId}${SEPARATOR}`
- : `${tableId}${SEPARATOR}${rowId}`
- return getDocParams(DocumentTypes.ROW, endOfKey, otherProps)
}
+
+ const endOfKey =
+ rowId == null ? `${tableId}${SEPARATOR}` : `${tableId}${SEPARATOR}${rowId}`
+
+ return getDocParams(DocumentTypes.ROW, endOfKey, otherProps)
}
/**
@@ -101,8 +101,12 @@ exports.generateRowID = tableId => {
/**
* Gets parameters for retrieving users, this is a utility function for the getDocParams function.
*/
-exports.getUserParams = (username = null, otherProps = {}) => {
- return getDocParams(DocumentTypes.USER, username, otherProps)
+exports.getUserParams = (username = "", otherProps = {}) => {
+ return getDocParams(
+ DocumentTypes.ROW,
+ `${ViewNames.USERS}${SEPARATOR}${DocumentTypes.USER}${SEPARATOR}${username}`,
+ otherProps
+ )
}
/**
@@ -111,7 +115,7 @@ exports.getUserParams = (username = null, otherProps = {}) => {
* @returns {string} The new user ID which the user doc can be stored under.
*/
exports.generateUserID = username => {
- return `${DocumentTypes.USER}${SEPARATOR}${username}`
+ return `${DocumentTypes.ROW}${SEPARATOR}${ViewNames.USERS}${SEPARATOR}${DocumentTypes.USER}${SEPARATOR}${username}`
}
/**
diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock
index c31727265a..a1049034c2 100644
--- a/packages/server/yarn.lock
+++ b/packages/server/yarn.lock
@@ -3868,6 +3868,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-data-descriptor "^1.0.0"
kind-of "^6.0.2"
+is-docker@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156"
+ integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==
+
is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
@@ -4027,6 +4032,13 @@ is-wsl@^1.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
+is-wsl@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
is-yarn-global@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
@@ -5648,6 +5660,14 @@ only@~0.0.2:
resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4"
integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=
+open@^7.3.0:
+ version "7.3.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-7.3.0.tgz#45461fdee46444f3645b6e14eb3ca94b82e1be69"
+ integrity sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==
+ dependencies:
+ is-docker "^2.0.0"
+ is-wsl "^2.1.1"
+
optionator@^0.8.1, optionator@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"