Renaming groups to workspaces.
This commit is contained in:
parent
e692223661
commit
004f719dde
|
@ -12,7 +12,7 @@ exports.GlobalRoles = {
|
|||
OWNER: "owner",
|
||||
ADMIN: "admin",
|
||||
BUILDER: "builder",
|
||||
GROUP_MANAGER: "group_manager",
|
||||
WORKSPACE_MANAGER: "workspace_manager",
|
||||
}
|
||||
|
||||
exports.Configs = {
|
||||
|
|
|
@ -19,7 +19,7 @@ exports.StaticDatabases = {
|
|||
|
||||
const DocumentTypes = {
|
||||
USER: "us",
|
||||
GROUP: "group",
|
||||
WORKSPACE: "workspace",
|
||||
CONFIG: "config",
|
||||
TEMPLATE: "template",
|
||||
APP: "app",
|
||||
|
@ -61,21 +61,21 @@ function getDocParams(docType, docId = null, otherProps = {}) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Generates a new group ID.
|
||||
* @returns {string} The new group ID which the group doc can be stored under.
|
||||
* Generates a new workspace ID.
|
||||
* @returns {string} The new workspace ID which the workspace doc can be stored under.
|
||||
*/
|
||||
exports.generateGroupID = () => {
|
||||
return `${DocumentTypes.GROUP}${SEPARATOR}${newid()}`
|
||||
exports.generateWorkspaceID = () => {
|
||||
return `${DocumentTypes.WORKSPACE}${SEPARATOR}${newid()}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameters for retrieving groups.
|
||||
* Gets parameters for retrieving workspaces.
|
||||
*/
|
||||
exports.getGroupParams = (id = "", otherProps = {}) => {
|
||||
exports.getWorkspaceParams = (id = "", otherProps = {}) => {
|
||||
return {
|
||||
...otherProps,
|
||||
startkey: `${DocumentTypes.GROUP}${SEPARATOR}${id}`,
|
||||
endkey: `${DocumentTypes.GROUP}${SEPARATOR}${id}${UNICODE_MAX}`,
|
||||
startkey: `${DocumentTypes.WORKSPACE}${SEPARATOR}${id}`,
|
||||
endkey: `${DocumentTypes.WORKSPACE}${SEPARATOR}${id}${UNICODE_MAX}`,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,14 +103,14 @@ exports.getGlobalUserParams = (globalId, otherProps = {}) => {
|
|||
|
||||
/**
|
||||
* Generates a template ID.
|
||||
* @param ownerId The owner/user of the template, this could be global or a group level.
|
||||
* @param ownerId The owner/user of the template, this could be global or a workspace level.
|
||||
*/
|
||||
exports.generateTemplateID = ownerId => {
|
||||
return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${SEPARATOR}${newid()}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameters for retrieving templates. Owner ID must be specified, either global or a group level.
|
||||
* Gets parameters for retrieving templates. Owner ID must be specified, either global or a workspace level.
|
||||
*/
|
||||
exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => {
|
||||
if (!templateId) {
|
||||
|
@ -214,8 +214,8 @@ exports.dbExists = async (CouchDB, dbName) => {
|
|||
* Generates a new configuration ID.
|
||||
* @returns {string} The new configuration ID which the config doc can be stored under.
|
||||
*/
|
||||
const generateConfigID = ({ type, group, user }) => {
|
||||
const scope = [type, group, user].filter(Boolean).join(SEPARATOR)
|
||||
const generateConfigID = ({ type, workspace, user }) => {
|
||||
const scope = [type, workspace, user].filter(Boolean).join(SEPARATOR)
|
||||
|
||||
return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}`
|
||||
}
|
||||
|
@ -223,8 +223,8 @@ const generateConfigID = ({ type, group, user }) => {
|
|||
/**
|
||||
* Gets parameters for retrieving configurations.
|
||||
*/
|
||||
const getConfigParams = ({ type, group, user }, otherProps = {}) => {
|
||||
const scope = [type, group, user].filter(Boolean).join(SEPARATOR)
|
||||
const getConfigParams = ({ type, workspace, user }, otherProps = {}) => {
|
||||
const scope = [type, workspace, user].filter(Boolean).join(SEPARATOR)
|
||||
|
||||
return {
|
||||
...otherProps,
|
||||
|
@ -234,15 +234,15 @@ const getConfigParams = ({ type, group, user }, otherProps = {}) => {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the most granular configuration document from the DB based on the type, group and userID passed.
|
||||
* Returns the most granular configuration document from the DB based on the type, workspace and userID passed.
|
||||
* @param {Object} db - db instance to query
|
||||
* @param {Object} scopes - the type, group and userID scopes of the configuration.
|
||||
* @param {Object} scopes - the type, workspace and userID scopes of the configuration.
|
||||
* @returns The most granular configuration document based on the scope.
|
||||
*/
|
||||
const getScopedFullConfig = async function (db, { type, user, group }) {
|
||||
const getScopedFullConfig = async function (db, { type, user, workspace }) {
|
||||
const response = await db.allDocs(
|
||||
getConfigParams(
|
||||
{ type, user, group },
|
||||
{ type, user, workspace },
|
||||
{
|
||||
include_docs: true,
|
||||
}
|
||||
|
@ -252,14 +252,14 @@ const getScopedFullConfig = async function (db, { type, user, group }) {
|
|||
function determineScore(row) {
|
||||
const config = row.doc
|
||||
|
||||
// Config is specific to a user and a group
|
||||
if (config._id.includes(generateConfigID({ type, user, group }))) {
|
||||
// Config is specific to a user and a workspace
|
||||
if (config._id.includes(generateConfigID({ type, user, workspace }))) {
|
||||
return 4
|
||||
} else if (config._id.includes(generateConfigID({ type, user }))) {
|
||||
// Config is specific to a user only
|
||||
return 3
|
||||
} else if (config._id.includes(generateConfigID({ type, group }))) {
|
||||
// Config is specific to a group only
|
||||
} else if (config._id.includes(generateConfigID({ type, workspace }))) {
|
||||
// Config is specific to a workspace only
|
||||
return 2
|
||||
} else if (config._id.includes(generateConfigID({ type }))) {
|
||||
// Config is specific to a type only
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports.definition = {
|
|||
properties: {
|
||||
text: {
|
||||
type: "string",
|
||||
title: "URL",
|
||||
title: "Log",
|
||||
},
|
||||
},
|
||||
required: ["text"],
|
||||
|
|
|
@ -102,7 +102,7 @@ exports.googlePreAuth = async (ctx, next) => {
|
|||
const db = new CouchDB(GLOBAL_DB)
|
||||
const config = await authPkg.db.getScopedConfig(db, {
|
||||
type: Configs.GOOGLE,
|
||||
group: ctx.query.group,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
const strategy = await google.strategyFactory(config)
|
||||
|
||||
|
@ -116,7 +116,7 @@ exports.googleAuth = async (ctx, next) => {
|
|||
|
||||
const config = await authPkg.db.getScopedConfig(db, {
|
||||
type: Configs.GOOGLE,
|
||||
group: ctx.query.group,
|
||||
workspace: ctx.query.workspace,
|
||||
})
|
||||
const strategy = await google.strategyFactory(config)
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
|||
|
||||
exports.save = async function (ctx) {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
const { type, group, user, config } = ctx.request.body
|
||||
const { type, workspace, user, config } = ctx.request.body
|
||||
|
||||
// Config does not exist yet
|
||||
if (!ctx.request.body._id) {
|
||||
ctx.request.body._id = generateConfigID({
|
||||
type,
|
||||
group,
|
||||
workspace,
|
||||
user,
|
||||
})
|
||||
}
|
||||
|
@ -65,17 +65,17 @@ exports.fetch = async function (ctx) {
|
|||
|
||||
/**
|
||||
* Gets the most granular config for a particular configuration type.
|
||||
* The hierarchy is type -> group -> user.
|
||||
* The hierarchy is type -> workspace -> user.
|
||||
*/
|
||||
exports.find = async function (ctx) {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
|
||||
const { userId, groupId } = ctx.query
|
||||
if (groupId && userId) {
|
||||
const group = await db.get(groupId)
|
||||
const userInGroup = group.users.some(groupUser => groupUser === userId)
|
||||
if (!ctx.user.admin && !userInGroup) {
|
||||
ctx.throw(400, `User is not in specified group: ${group}.`)
|
||||
const { userId, workspaceId } = ctx.query
|
||||
if (workspaceId && userId) {
|
||||
const workspace = await db.get(workspaceId)
|
||||
const userInWorkspace = workspace.users.some(workspaceUser => workspaceUser === userId)
|
||||
if (!ctx.user.admin && !userInWorkspace) {
|
||||
ctx.throw(400, `User is not in specified workspace: ${workspace}.`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ exports.find = async function (ctx) {
|
|||
const scopedConfig = await getScopedFullConfig(db, {
|
||||
type: ctx.params.type,
|
||||
user: userId,
|
||||
group: groupId,
|
||||
workspace: workspaceId,
|
||||
})
|
||||
|
||||
if (scopedConfig) {
|
||||
|
|
|
@ -5,7 +5,7 @@ const authPkg = require("@budibase/auth")
|
|||
const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name
|
||||
|
||||
exports.sendEmail = async ctx => {
|
||||
const { groupId, email, userId, purpose, contents, from, subject } =
|
||||
const { workspaceId, email, userId, purpose, contents, from, subject } =
|
||||
ctx.request.body
|
||||
let user
|
||||
if (userId) {
|
||||
|
@ -13,7 +13,7 @@ exports.sendEmail = async ctx => {
|
|||
user = await db.get(userId)
|
||||
}
|
||||
const response = await sendEmail(email, purpose, {
|
||||
groupId,
|
||||
workspaceId,
|
||||
user,
|
||||
contents,
|
||||
from,
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
const CouchDB = require("../../../db")
|
||||
const { getGroupParams, generateGroupID, StaticDatabases } =
|
||||
const { getWorkspaceParams, generateWorkspaceID, StaticDatabases } =
|
||||
require("@budibase/auth").db
|
||||
|
||||
const GLOBAL_DB = StaticDatabases.GLOBAL.name
|
||||
|
||||
exports.save = async function (ctx) {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
const groupDoc = ctx.request.body
|
||||
const workspaceDoc = ctx.request.body
|
||||
|
||||
// Group does not exist yet
|
||||
if (!groupDoc._id) {
|
||||
groupDoc._id = generateGroupID()
|
||||
// workspace does not exist yet
|
||||
if (!workspaceDoc._id) {
|
||||
workspaceDoc._id = generateWorkspaceID()
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await db.post(groupDoc)
|
||||
const response = await db.post(workspaceDoc)
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
|
@ -27,7 +27,7 @@ exports.save = async function (ctx) {
|
|||
exports.fetch = async function (ctx) {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
const response = await db.allDocs(
|
||||
getGroupParams(undefined, {
|
||||
getWorkspaceParams(undefined, {
|
||||
include_docs: true,
|
||||
})
|
||||
)
|
||||
|
@ -49,7 +49,7 @@ exports.destroy = async function (ctx) {
|
|||
|
||||
try {
|
||||
await db.remove(id, rev)
|
||||
ctx.body = { message: "Group deleted successfully" }
|
||||
ctx.body = { message: "Workspace deleted successfully" }
|
||||
} catch (err) {
|
||||
ctx.throw(err.status, err)
|
||||
}
|
|
@ -46,7 +46,7 @@ function buildConfigSaveValidation() {
|
|||
return joiValidator.body(Joi.object({
|
||||
_id: Joi.string().optional(),
|
||||
_rev: Joi.string().optional(),
|
||||
group: Joi.string().optional(),
|
||||
workspace: Joi.string().optional(),
|
||||
type: Joi.string().valid(...Object.values(Configs)).required(),
|
||||
config: Joi.alternatives()
|
||||
.conditional("type", {
|
||||
|
|
|
@ -12,8 +12,8 @@ function buildEmailSendValidation() {
|
|||
return joiValidator.body(Joi.object({
|
||||
email: Joi.string().email(),
|
||||
purpose: Joi.string().valid(...Object.values(EmailTemplatePurpose)),
|
||||
groupId: Joi.string().allow("", null),
|
||||
fromt: Joi.string().allow("", null),
|
||||
workspaceId: Joi.string().allow("", null),
|
||||
from: Joi.string().allow("", null),
|
||||
contents: Joi.string().allow("", null),
|
||||
subject: Joi.string().allow("", null),
|
||||
}).required().unknown(true))
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/admin/groups")
|
||||
const controller = require("../../controllers/admin/workspaces")
|
||||
const joiValidator = require("../../../middleware/joi-validator")
|
||||
const adminOnly = require("../../../middleware/adminOnly")
|
||||
const Joi = require("joi")
|
||||
|
||||
const router = Router()
|
||||
|
||||
function buildGroupSaveValidation() {
|
||||
function buildWorkspaceSaveValidation() {
|
||||
// prettier-ignore
|
||||
return joiValidator.body(Joi.object({
|
||||
_id: Joi.string().optional(),
|
||||
|
@ -26,13 +26,13 @@ function buildGroupSaveValidation() {
|
|||
|
||||
router
|
||||
.post(
|
||||
"/api/admin/groups",
|
||||
"/api/admin/workspaces",
|
||||
adminOnly,
|
||||
buildGroupSaveValidation(),
|
||||
buildWorkspaceSaveValidation(),
|
||||
controller.save
|
||||
)
|
||||
.get("/api/admin/groups", controller.fetch)
|
||||
.delete("/api/admin/groups/:id", adminOnly, controller.destroy)
|
||||
.get("/api/admin/groups/:id", controller.find)
|
||||
.delete("/api/admin/workspaces/:id", adminOnly, controller.destroy)
|
||||
.get("/api/admin/workspaces", controller.fetch)
|
||||
.get("/api/admin/workspaces/:id", controller.find)
|
||||
|
||||
module.exports = router
|
|
@ -1,6 +1,6 @@
|
|||
const userRoutes = require("./admin/users")
|
||||
const configRoutes = require("./admin/configs")
|
||||
const groupRoutes = require("./admin/groups")
|
||||
const workspaceRoutes = require("./admin/workspaces")
|
||||
const templateRoutes = require("./admin/templates")
|
||||
const emailRoutes = require("./admin/email")
|
||||
const authRoutes = require("./admin/auth")
|
||||
|
@ -11,7 +11,7 @@ const appRoutes = require("./app")
|
|||
exports.routes = [
|
||||
configRoutes,
|
||||
userRoutes,
|
||||
groupRoutes,
|
||||
workspaceRoutes,
|
||||
authRoutes,
|
||||
appRoutes,
|
||||
templateRoutes,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
email: require("../../../controllers/admin/email"),
|
||||
groups: require("../../../controllers/admin/groups"),
|
||||
workspaces: require("../../../controllers/admin/workspaces"),
|
||||
config: require("../../../controllers/admin/configs"),
|
||||
templates: require("../../../controllers/admin/templates"),
|
||||
users: require("../../../controllers/admin/users"),
|
||||
|
|
|
@ -8,10 +8,6 @@ exports.UserStatus = {
|
|||
INACTIVE: "inactive",
|
||||
}
|
||||
|
||||
exports.Groups = {
|
||||
ALL_USERS: "all_users",
|
||||
}
|
||||
|
||||
exports.Configs = Configs
|
||||
|
||||
exports.ConfigUploads = {
|
||||
|
|
|
@ -101,31 +101,31 @@ async function buildEmail(purpose, email, context, { user, contents } = {}) {
|
|||
/**
|
||||
* Utility function for finding most valid SMTP configuration.
|
||||
* @param {object} db The CouchDB database which is to be looked up within.
|
||||
* @param {string|null} groupId If using finer grain control of configs a group can be used.
|
||||
* @param {string|null} workspaceId If using finer grain control of configs a workspace can be used.
|
||||
* @return {Promise<object|null>} returns the SMTP configuration if it exists
|
||||
*/
|
||||
async function getSmtpConfiguration(db, groupId = null) {
|
||||
async function getSmtpConfiguration(db, workspaceId = null) {
|
||||
const params = {
|
||||
type: Configs.SMTP,
|
||||
}
|
||||
if (groupId) {
|
||||
params.group = groupId
|
||||
if (workspaceId) {
|
||||
params.workspace = workspaceId
|
||||
}
|
||||
return getScopedConfig(db, params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a SMTP config exists based on passed in parameters.
|
||||
* @param groupId
|
||||
* @param workspaceId
|
||||
* @return {Promise<boolean>} returns true if there is a configuration that can be used.
|
||||
*/
|
||||
exports.isEmailConfigured = async (groupId = null) => {
|
||||
exports.isEmailConfigured = async (workspaceId = null) => {
|
||||
// when "testing" simply return true
|
||||
if (TEST_MODE) {
|
||||
return true
|
||||
}
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
const config = await getSmtpConfiguration(db, groupId)
|
||||
const config = await getSmtpConfiguration(db, workspaceId)
|
||||
return config != null
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ exports.isEmailConfigured = async (groupId = null) => {
|
|||
* send an email using it.
|
||||
* @param {string} email The email address to send to.
|
||||
* @param {string} purpose The purpose of the email being sent (e.g. reset password).
|
||||
* @param {string|undefined} groupId If finer grain controls being used then this will lookup config for group.
|
||||
* @param {string|undefined} workspaceId If finer grain controls being used then this will lookup config for workspace.
|
||||
* @param {object|undefined} user If sending to an existing user the object can be provided, this is used in the context.
|
||||
* @param {string|undefined} from If sending from an address that is not what is configured in the SMTP config.
|
||||
* @param {string|undefined} contents If sending a custom email then can supply contents which will be added to it.
|
||||
|
@ -146,10 +146,10 @@ exports.isEmailConfigured = async (groupId = null) => {
|
|||
exports.sendEmail = async (
|
||||
email,
|
||||
purpose,
|
||||
{ groupId, user, from, contents, subject, info } = {}
|
||||
{ workspaceId, user, from, contents, subject, info } = {}
|
||||
) => {
|
||||
const db = new CouchDB(GLOBAL_DB)
|
||||
let config = (await getSmtpConfiguration(db, groupId)) || {}
|
||||
let config = (await getSmtpConfiguration(db, workspaceId)) || {}
|
||||
if (Object.keys(config).length === 0 && !TEST_MODE) {
|
||||
throw "Unable to find SMTP configuration."
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue