diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js
index 32034bd731..90b44c43b7 100644
--- a/packages/auth/src/db/utils.js
+++ b/packages/auth/src/db/utils.js
@@ -70,12 +70,11 @@ exports.getUserParams = (email = "", otherProps = {}) => {
* Generates a new configuration ID.
* @returns {string} The new configuration ID which the config doc can be stored under.
*/
-exports.generateConfigID = (type = "", group = "") => {
- group += SEPARATOR
+exports.generateConfigID = (type = "", group = "", user = "") => {
+ // group += SEPARATOR
+ const scope = [type, group, user].join(SEPARATOR)
- return `${
- DocumentTypes.CONFIG
- }${SEPARATOR}${type}${SEPARATOR}${group}${newid()}`
+ return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${newid()}`
}
/**
diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js
index 4c6ece1b62..4ef30c9f02 100644
--- a/packages/auth/src/index.js
+++ b/packages/auth/src/index.js
@@ -1,10 +1,10 @@
const passport = require("koa-passport")
const LocalStrategy = require("passport-local").Strategy
const JwtStrategy = require("passport-jwt").Strategy
-// const GoogleStrategy = require("passport-google-oauth").Strategy
+const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy
const database = require("./db")
-const { StaticDatabases } = require("./db/utils")
-const { jwt, local, authenticated } = require("./middleware")
+const { StaticDatabases, DocumentTypes } = require("./db/utils")
+const { jwt, local, google, authenticated } = require("./middleware")
const { Cookies, UserStatus } = require("./constants")
const { hash, compare } = require("./hashing")
const {
@@ -27,7 +27,7 @@ const {
// Strategies
passport.use(new LocalStrategy(local.options, local.authenticate))
passport.use(new JwtStrategy(jwt.options, jwt.authenticate))
-// passport.use(new GoogleStrategy(google.options, google.authenticate))
+passport.use(new GoogleStrategy(google.options, google.authenticate))
passport.serializeUser((user, done) => done(null, user))
@@ -50,6 +50,7 @@ module.exports = {
passport,
Cookies,
UserStatus,
+ DocumentTypes,
StaticDatabases,
generateUserID,
getUserParams,
diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js
index 6246e5e768..9113fba1cf 100644
--- a/packages/auth/src/middleware/passport/google.js
+++ b/packages/auth/src/middleware/passport/google.js
@@ -1,18 +1,54 @@
const env = require("../../environment")
+const jwt = require("jsonwebtoken")
+const database = require("../../db")
+const { StaticDatabases, generateUserID } = require("../../db/utils")
exports.options = {
- clientId: env.GOOGLE_CLIENT_ID,
+ clientID: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET,
callbackURL: env.GOOGLE_AUTH_CALLBACK_URL,
}
exports.authenticate = async function(token, tokenSecret, profile, done) {
- console.log({
- token,
- tokenSecret,
- profile,
- done,
+ if (!profile._json.email) return done(null, false, "Email Required.")
+
+ // Check the user exists in the instance DB by email
+ const db = new database.CouchDB(StaticDatabases.GLOBAL.name)
+
+ let dbUser
+ const userId = generateUserID(profile._json.email)
+
+ try {
+ // use the google profile id
+ dbUser = await db.get(userId)
+ } catch (err) {
+ console.error("Google user not found. Creating..")
+ // create the user
+ const user = {
+ _id: userId,
+ provider: profile.provider,
+ roles: {},
+ builder: {
+ global: true,
+ },
+ ...profile._json,
+ }
+ const response = await db.post(user)
+
+ dbUser = user
+ dbUser._rev = response.rev
+ }
+
+ // authenticate
+ const payload = {
+ userId: dbUser._id,
+ builder: dbUser.builder,
+ email: dbUser.email,
+ }
+
+ dbUser.token = jwt.sign(payload, env.JWT_SECRET, {
+ expiresIn: "1 day",
})
- // retrieve user ...
- // fetchUser().then(user => done(null, user))
+
+ return done(null, dbUser)
}
diff --git a/packages/builder/src/components/login/LoginForm.svelte b/packages/builder/src/components/login/LoginForm.svelte
index 7e32efb7c5..55d1ee3bf5 100644
--- a/packages/builder/src/components/login/LoginForm.svelte
+++ b/packages/builder/src/components/login/LoginForm.svelte
@@ -46,6 +46,7 @@
+ Sign In with Google
diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js
index e9fc8a3942..10f1d2cf2b 100644
--- a/packages/worker/src/api/controllers/admin/configs.js
+++ b/packages/worker/src/api/controllers/admin/configs.js
@@ -1,17 +1,47 @@
const CouchDB = require("../../../db")
-const { StaticDatabases } = require("@budibase/auth")
-const { generateConfigID } = require("@budibase/auth")
-const { getConfigParams } = require("@budibase/auth/src/db/utils")
+const { StaticDatabases, DocumentTypes } = require("@budibase/auth")
+const { generateConfigID, getConfigParams } = require("@budibase/auth")
+const { SEPARATOR } = require("@budibase/auth/src/db/utils")
+const { Configs } = require("../../../constants")
const GLOBAL_DB = StaticDatabases.GLOBAL.name
+exports.configStatus = async function(ctx) {
+ const db = new CouchDB(GLOBAL_DB)
+ let configured = {}
+
+ // check for super admin user
+ try {
+ configured.user = true
+ } catch (err) {
+ configured.user = false
+ }
+
+ // check for SMTP config
+ try {
+ const response = await db.allDocs(
+ getConfigParams(`${DocumentTypes.CONFIG}${SEPARATOR}${Configs.SMTP}`)
+ )
+ console.log(response)
+ configured.smtp = true
+ } catch (err) {
+ configured.smtp = false
+ }
+
+ ctx.body = configured
+}
+
exports.save = async function(ctx) {
const db = new CouchDB(GLOBAL_DB)
const configDoc = ctx.request.body
// Config does not exist yet
if (!configDoc._id) {
- configDoc._id = generateConfigID(configDoc.type, configDoc.group)
+ configDoc._id = generateConfigID(
+ configDoc.type,
+ configDoc.group,
+ configDoc.user
+ )
}
try {
diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js
index 03589ab457..d2aaf552e0 100644
--- a/packages/worker/src/api/controllers/auth.js
+++ b/packages/worker/src/api/controllers/auth.js
@@ -1,4 +1,38 @@
-const { passport, Cookies, clearCookie } = require("@budibase/auth")
+const {
+ passport,
+ Cookies,
+ StaticDatabases,
+ clearCookie,
+} = require("@budibase/auth")
+const CouchDB = require("../../db")
+
+const GLOBAL_DB = StaticDatabases.GLOBAL.name
+
+async function setToken(ctx) {
+ return async function(err, user) {
+ if (err) {
+ return ctx.throw(403, "Unauthorized")
+ }
+
+ const expires = new Date()
+ expires.setDate(expires.getDate() + 1)
+
+ if (!user) {
+ return ctx.throw(403, "Unauthorized")
+ }
+
+ ctx.cookies.set(Cookies.Auth, user.token, {
+ expires,
+ path: "/",
+ httpOnly: false,
+ overwrite: true,
+ })
+
+ delete user.token
+
+ ctx.body = { user }
+ }
+}
exports.authenticate = async (ctx, next) => {
return passport.authenticate("local", async (err, user) => {
@@ -31,10 +65,30 @@ exports.logout = async ctx => {
ctx.body = { message: "User logged out" }
}
-exports.googleAuth = async () => {
- // return passport.authenticate("google")
-}
+exports.googleAuth = async (ctx, next) => {
+ return passport.authenticate(
+ "google",
+ { successRedirect: "/", failureRedirect: "/" },
+ async (err, user) => {
+ if (err) {
+ return ctx.throw(403, "Unauthorized")
+ }
-exports.googleAuth = async () => {
- // return passport.authenticate("google")
+ const expires = new Date()
+ expires.setDate(expires.getDate() + 1)
+
+ if (!user) {
+ return ctx.throw(403, "Unauthorized")
+ }
+
+ ctx.cookies.set(Cookies.Auth, user.token, {
+ expires,
+ path: "/",
+ httpOnly: false,
+ overwrite: true,
+ })
+
+ ctx.redirect("/")
+ }
+ )(ctx, next)
}
diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js
index 5b7354bfc3..0399026cf2 100644
--- a/packages/worker/src/api/routes/admin/configs.js
+++ b/packages/worker/src/api/routes/admin/configs.js
@@ -10,7 +10,7 @@ const router = Router()
function buildConfigSaveValidation() {
// prettier-ignore
return joiValidator.body(Joi.object({
- type: Joi.string().valid(...Object.values(Configs)).required()
+ type: Joi.string().valid(...Object.values(Configs)).required(),
}).required().unknown(true))
}
@@ -21,6 +21,7 @@ router
authenticated,
controller.save
)
+ .post("/api/admin/config/status", controller.configStatus)
.delete("/api/admin/configs/:id", authenticated, controller.destroy)
.get("/api/admin/configs", authenticated, controller.fetch)
.get("/api/admin/configs/:id", authenticated, controller.find)
diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js
index deea678c63..ac87ef977a 100644
--- a/packages/worker/src/api/routes/auth.js
+++ b/packages/worker/src/api/routes/auth.js
@@ -1,19 +1,17 @@
const Router = require("@koa/router")
const { passport } = require("@budibase/auth")
const authController = require("../controllers/auth")
+const context = require("koa/lib/context")
const router = Router()
router
.post("/api/admin/auth", authController.authenticate)
- .post("/api/admin/auth/logout", authController.logout)
- .get("/api/auth/google", passport.authenticate("google"))
.get(
- "/api/auth/google/callback",
- passport.authenticate("google", {
- successRedirect: "/app",
- failureRedirect: "/",
- })
+ "/api/admin/auth/google",
+ passport.authenticate("google", { scope: ["profile", "email"] })
)
+ .get("/api/admin/auth/google/callback", authController.googleAuth)
+ .post("/api/admin/auth/logout", authController.logout)
module.exports = router