diff --git a/backend/src/db/api/users.js b/backend/src/db/api/users.js index f275a25..a18b659 100644 --- a/backend/src/db/api/users.js +++ b/backend/src/db/api/users.js @@ -907,6 +907,8 @@ module.exports = class UsersDBApi { { password, authenticationUid: id, + passwordResetToken: null, + passwordResetTokenExpiresAt: null, updatedById: currentUser.id, }, { transaction }, diff --git a/backend/src/routes/auth.js b/backend/src/routes/auth.js index 31d62cb..9bb5fc0 100644 --- a/backend/src/routes/auth.js +++ b/backend/src/routes/auth.js @@ -9,6 +9,11 @@ const wrapAsync = require('../helpers').wrapAsync; const router = express.Router(); +function getRequestOrigin(req) { + const referer = req.headers.referer || `${req.protocol}://${req.get('host')}${req.originalUrl}`; + return new URL(referer).origin; +} + /** * @swagger * components: @@ -104,14 +109,13 @@ router.post('/send-email-address-verification-email', passport.authenticate('jwt throw new ForbiddenError(); } - await AuthService.sendEmailAddressVerificationEmail(req.currentUser.email); + await AuthService.sendEmailAddressVerificationEmail(req.currentUser.email, getRequestOrigin(req)); const payload = true; res.status(200).send(payload); })); router.post('/send-password-reset-email', wrapAsync(async (req, res) => { - const link = new URL(req.headers.referer); - await AuthService.sendPasswordResetEmail(req.body.email, 'register', link.host,); + await AuthService.sendPasswordResetEmail(req.body.email, 'register', getRequestOrigin(req)); const payload = true; res.status(200).send(payload); })); @@ -140,7 +144,6 @@ router.post('/send-password-reset-email', wrapAsync(async (req, res) => { */ router.post('/signup', wrapAsync(async (req, res) => { - const link = new URL(req.headers.referer); const payload = await AuthService.signup( req.body.email, req.body.password, @@ -148,7 +151,7 @@ router.post('/signup', wrapAsync(async (req, res) => { req.body.organizationId, req, - link.host, + getRequestOrigin(req), ) res.status(200).send(payload); })); diff --git a/backend/src/routes/users.js b/backend/src/routes/users.js index 69f227e..26c9a31 100644 --- a/backend/src/routes/users.js +++ b/backend/src/routes/users.js @@ -10,6 +10,11 @@ const config = require('../config'); const router = express.Router(); +function getRequestOrigin(req) { + const referer = req.headers.referer || `${req.protocol}://${req.get('host')}${req.originalUrl}`; + return new URL(referer).origin; +} + const { parse } = require('json2csv'); @@ -86,9 +91,7 @@ router.use(checkCrudPermissions('users')); * description: Some server error */ router.post('/', wrapAsync(async (req, res) => { - const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`; - const link = new URL(referer); - await UsersService.create(req.body.data, req.currentUser, true, link.host); + await UsersService.create(req.body.data, req.currentUser, true, getRequestOrigin(req)); const payload = true; res.status(200).send(payload); })); @@ -129,9 +132,7 @@ router.post('/', wrapAsync(async (req, res) => { * */ router.post('/bulk-import', wrapAsync(async (req, res) => { - const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`; - const link = new URL(referer); - await UsersService.bulkImport(req, res, true, link.host); + await UsersService.bulkImport(req, res, true, getRequestOrigin(req)); const payload = true; res.status(200).send(payload); })); diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt new file mode 100644 index 0000000..886b049 --- /dev/null +++ b/frontend/public/robots.txt @@ -0,0 +1,9 @@ +User-agent: * +Allow: / +Disallow: /api/ +Disallow: /api-docs +Disallow: /login +Disallow: /register +Disallow: /forgot +Disallow: /password-reset +Disallow: /verify-email diff --git a/frontend/public/site.webmanifest b/frontend/public/site.webmanifest new file mode 100644 index 0000000..4515c8d --- /dev/null +++ b/frontend/public/site.webmanifest @@ -0,0 +1,17 @@ +{ + "name": "Legacy Business Builder", + "short_name": "Legacy Builder", + "description": "AI-powered workflow to plan, fund, build, comply, staff, market, and launch a business from an idea.", + "start_url": "/", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#4f46e5", + "icons": [ + { + "src": "/favicon.svg", + "sizes": "any", + "type": "image/svg+xml", + "purpose": "any" + } + ] +} diff --git a/frontend/src/components/AsideMenuLayer.tsx b/frontend/src/components/AsideMenuLayer.tsx index f840be1..22db28d 100644 --- a/frontend/src/components/AsideMenuLayer.tsx +++ b/frontend/src/components/AsideMenuLayer.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { mdiLogout, mdiClose } from '@mdi/js' +import { mdiClose } from '@mdi/js' import BaseIcon from './BaseIcon' import AsideMenuList from './AsideMenuList' import { MenuAsideItem } from '../interfaces' @@ -7,7 +7,8 @@ import { useAppDispatch, useAppSelector } from '../stores/hooks' import Link from 'next/link'; import { createAsyncThunk } from '@reduxjs/toolkit'; import axios from 'axios'; - +import { appTitle } from '../config'; +import { getPrimaryWorkspaceMeta } from '../helpers/appNavigation'; type Props = { menu: MenuAsideItem[] @@ -31,6 +32,7 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props const { currentUser } = useAppSelector((state) => state.auth); const organizationsId = currentUser?.organizations?.id; const [organizations, setOrganizations] = React.useState(null); + const primaryWorkspace = getPrimaryWorkspaceMeta(currentUser); const fetchOrganizations = createAsyncThunk('/org-for-auth', async () => { try { @@ -52,6 +54,9 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props organizationName = organizationName?.substring(0, 25) + '...'; } + const brandSubLabel = organizationName + ? `${organizationName} · Open ${primaryWorkspace.label}` + : `Workspace home · Open ${primaryWorkspace.label}`; return (