mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-06 12:12:42 +00:00
Merge branch 'dependabot/npm_and_yarn/react-router-dom-7.0.2' of https://github.com/naturalcrit/homebrewery into dependabot/npm_and_yarn/react-router-dom-7.0.2
This commit is contained in:
25
.github/pull_request_template.md
vendored
25
.github/pull_request_template.md
vendored
@@ -1,26 +1,29 @@
|
|||||||
<!--
|
> [!TIP]
|
||||||
Before submitting a Pull Request, please consider the following to speed up reviews:
|
> Before submitting a Pull Request, please consider the following to speed up reviews:
|
||||||
- 👷♀️ Create small PRs. Large PRs can usually be broken down into incremental PRs.
|
> - 👷♀️ Create small PRs. Large PRs can usually be broken down into incremental PRs.
|
||||||
- 🚩 Do you already have several open PRs? Consider finishing or asking for help with existing PRs first.
|
> - 🚩 Do you already have several open PRs? Consider finishing or asking for help with existing PRs first.
|
||||||
- 🔧 Does your PR reference a discussed and approved issue, especially for personal or edge-case requests?
|
> - 🔧 Does your PR reference a discussed and approved issue, especially for personal or edge-case requests?
|
||||||
- 💡 Is the solution agreed upon? Save rework time by discussing strategy before coding.
|
> - 💡 Is the solution agreed upon? Save rework time by discussing strategy before coding.
|
||||||
-->
|
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
_Describe what your PR accomplishes. Consider walking through the main changes to aid reviewers in following your code, especially if it covers multiple files._
|
||||||
|
|
||||||
## Related Issues or Discussions
|
## Related Issues or Discussions
|
||||||
|
|
||||||
|
> [!CAUTION]
|
||||||
|
> If no issue exists yet, create it, and get agreement on the approach (or paste in a previous agreement from chat, etc.) before moving forward. (Experimental PRs are OK without prior discussion, but do not expect to get merged.)
|
||||||
|
|
||||||
- Closes #
|
- Closes #
|
||||||
|
|
||||||
## QA Instructions, Screenshots, Recordings
|
## QA Instructions, Screenshots, Recordings
|
||||||
|
|
||||||
_Please replace this line with instructions on how to test or view your changes, as well as any before/after
|
_Replace this line with instructions on how to test or view your changes, as well as any before/after
|
||||||
images for UI changes._
|
screenshots or recordings for UI changes._
|
||||||
|
|
||||||
### Reviewer Checklist
|
### Reviewer Checklist
|
||||||
|
|
||||||
_Please replace the list below with specific features you want reviewers to look at._
|
_Replace the list below with specific features you want reviewers to look at._
|
||||||
|
|
||||||
*Reviewers, refer to this list when testing features, or suggest new items *
|
*Reviewers, refer to this list when testing features, or suggest new items *
|
||||||
- [ ] Verify new features are functional
|
- [ ] Verify new features are functional
|
||||||
@@ -32,5 +35,3 @@ _Please replace the list below with specific features you want reviewers to look
|
|||||||
- [ ] Feature A handles negative numbers
|
- [ ] Feature A handles negative numbers
|
||||||
- [ ] Identify opportunities for simplification and refactoring
|
- [ ] Identify opportunities for simplification and refactoring
|
||||||
- [ ] Check for code legibility and appropriate comments
|
- [ ] Check for code legibility and appropriate comments
|
||||||
|
|
||||||
<details><summary>Copy this list</summary>
|
|
||||||
|
|||||||
@@ -91,6 +91,7 @@
|
|||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
|
"cors": "^2.8.5",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.3",
|
"dedent-tabs": "^0.10.3",
|
||||||
"dompurify": "^3.2.3",
|
"dompurify": "^3.2.3",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Set working directory to project root
|
// Set working directory to project root
|
||||||
import { dirname } from 'path';
|
import { dirname } from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import packageJSON from './../package.json' with { type: "json" };
|
import packageJSON from './../package.json' with { type: 'json' };
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
process.chdir(`${__dirname}/..`);
|
process.chdir(`${__dirname}/..`);
|
||||||
@@ -26,7 +26,7 @@ import serveCompressedStaticAssets from './static-assets.mv.js';
|
|||||||
import sanitizeFilename from 'sanitize-filename';
|
import sanitizeFilename from 'sanitize-filename';
|
||||||
import asyncHandler from 'express-async-handler';
|
import asyncHandler from 'express-async-handler';
|
||||||
import templateFn from '../client/template.js';
|
import templateFn from '../client/template.js';
|
||||||
import {model as HomebrewModel } from './homebrew.model.js';
|
import { model as HomebrewModel } from './homebrew.model.js';
|
||||||
|
|
||||||
import { DEFAULT_BREW } from './brewDefaults.js';
|
import { DEFAULT_BREW } from './brewDefaults.js';
|
||||||
import { splitTextStyleAndMetadata } from '../shared/helpers.js';
|
import { splitTextStyleAndMetadata } from '../shared/helpers.js';
|
||||||
@@ -47,7 +47,7 @@ const sanitizeBrew = (brew, accessType)=>{
|
|||||||
return brew;
|
return brew;
|
||||||
};
|
};
|
||||||
|
|
||||||
app.set('trust proxy', 1 /* number of proxies between user and server */)
|
app.set('trust proxy', 1 /* number of proxies between user and server */);
|
||||||
|
|
||||||
app.use('/', serveCompressedStaticAssets(`build`));
|
app.use('/', serveCompressedStaticAssets(`build`));
|
||||||
app.use(contentNegotiation);
|
app.use(contentNegotiation);
|
||||||
@@ -55,14 +55,51 @@ app.use(bodyParser.json({ limit: '25mb' }));
|
|||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(forceSSL);
|
app.use(forceSSL);
|
||||||
|
|
||||||
|
import cors from 'cors';
|
||||||
|
|
||||||
|
const nodeEnv = config.get('node_env');
|
||||||
|
const isLocalEnvironment = config.get('local_environments').includes(nodeEnv);
|
||||||
|
|
||||||
|
const corsOptions = {
|
||||||
|
origin : (origin, callback)=>{
|
||||||
|
|
||||||
|
const allowedOrigins = [
|
||||||
|
'https://homebrewery.naturalcrit.com',
|
||||||
|
'https://naturalcrit.com',
|
||||||
|
'https://naturalcrit-stage.herokuapp.com',
|
||||||
|
'https://homebrewery-stage.herokuapp.com',
|
||||||
|
];
|
||||||
|
|
||||||
|
if(isLocalEnvironment) {
|
||||||
|
allowedOrigins.push('http://localhost:8000', 'http://localhost:8010');
|
||||||
|
}
|
||||||
|
|
||||||
|
const herokuRegex = /^https:\/\/(?:homebrewery-pr-\d+\.herokuapp\.com|naturalcrit-pr-\d+\.herokuapp\.com)$/; // Matches any Heroku app
|
||||||
|
|
||||||
|
if(!origin || allowedOrigins.includes(origin) || herokuRegex.test(origin)) {
|
||||||
|
callback(null, true);
|
||||||
|
} else {
|
||||||
|
console.log(origin, 'not allowed');
|
||||||
|
callback(new Error('Not allowed by CORS, if you think this is an error, please contact us'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods : ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||||
|
credentials : true,
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(cors(corsOptions));
|
||||||
|
|
||||||
//Account Middleware
|
//Account Middleware
|
||||||
app.use((req, res, next)=>{
|
app.use((req, res, next)=>{
|
||||||
|
console.log('passing through acc middleware, checking for cookies now: does cookies exist? ', !!req.cookies, ', ok, does the session cookie exist? ', !!req.cookies.nc_session);
|
||||||
if(req.cookies && req.cookies.nc_session){
|
if(req.cookies && req.cookies.nc_session){
|
||||||
try {
|
try {
|
||||||
req.account = jwt.decode(req.cookies.nc_session, config.get('secret'));
|
req.account = jwt.decode(req.cookies.nc_session, config.get('secret'));
|
||||||
//console.log("Just loaded up JWT from cookie:");
|
//console.log("Just loaded up JWT from cookie:");
|
||||||
//console.log(req.account);
|
//console.log(req.account);
|
||||||
} catch (e){}
|
} catch (e){
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req.config = {
|
req.config = {
|
||||||
@@ -273,7 +310,7 @@ app.get('/user/:username', async (req, res, next)=>{
|
|||||||
console.log(err);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
brews.forEach(brew => brew.stubbed = true); //All brews from MongoDB are "stubbed"
|
brews.forEach((brew)=>brew.stubbed = true); //All brews from MongoDB are "stubbed"
|
||||||
|
|
||||||
if(ownAccount && req?.account?.googleId){
|
if(ownAccount && req?.account?.googleId){
|
||||||
const auth = await GoogleActions.authCheck(req.account, res);
|
const auth = await GoogleActions.authCheck(req.account, res);
|
||||||
@@ -312,6 +349,37 @@ app.get('/user/:username', async (req, res, next)=>{
|
|||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Change author name on brews
|
||||||
|
app.put('/api/user/rename', async (req, res)=>{
|
||||||
|
const { username, newUsername } = req.body;
|
||||||
|
|
||||||
|
//this next logs will be removed in a next PR, as i need to get this live to test if req.account is created when passing the request from naturalcrit.com
|
||||||
|
|
||||||
|
console.log(`is user ${req.account.username} equal to ${username}? ${req.account.username === username} ${req.account.username === username && 'then add the damn auth for renaming!'}`);
|
||||||
|
console.log('renaming');
|
||||||
|
|
||||||
|
if(!username || !newUsername) {
|
||||||
|
return res.status(400).json({ error: 'Username and newUsername are required.' });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const brews = await HomebrewModel.getByUser(username, true, ['authors']);
|
||||||
|
const renamePromises = brews.map(async (brew)=>{
|
||||||
|
const updatedAuthors = brew.authors.map((author)=>author === username ? newUsername : author
|
||||||
|
);
|
||||||
|
return HomebrewModel.updateOne(
|
||||||
|
{ _id: brew._id },
|
||||||
|
{ $set: { authors: updatedAuthors } }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await Promise.all(renamePromises);
|
||||||
|
|
||||||
|
return res.json({ success: true, message: `Brews for ${username} renamed to ${newUsername}.` });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error renaming brews:', error);
|
||||||
|
return res.status(500).json({ error: 'Failed to rename brews.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//Edit Page
|
//Edit Page
|
||||||
app.get('/edit/:id', asyncHandler(getBrew('edit')), asyncHandler(async(req, res, next)=>{
|
app.get('/edit/:id', asyncHandler(getBrew('edit')), asyncHandler(async(req, res, next)=>{
|
||||||
req.brew = req.brew.toObject ? req.brew.toObject() : req.brew;
|
req.brew = req.brew.toObject ? req.brew.toObject() : req.brew;
|
||||||
@@ -399,7 +467,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r
|
|||||||
app.get('/account', asyncHandler(async (req, res, next)=>{
|
app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||||
const data = {};
|
const data = {};
|
||||||
data.title = 'Account Information Page';
|
data.title = 'Account Information Page';
|
||||||
|
|
||||||
if(!req.account) {
|
if(!req.account) {
|
||||||
res.set('WWW-Authenticate', 'Bearer realm="Authorization Required"');
|
res.set('WWW-Authenticate', 'Bearer realm="Authorization Required"');
|
||||||
const error = new Error('No valid account');
|
const error = new Error('No valid account');
|
||||||
@@ -413,7 +481,7 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
|||||||
let googleCount = [];
|
let googleCount = [];
|
||||||
if(req.account) {
|
if(req.account) {
|
||||||
if(req.account.googleId) {
|
if(req.account.googleId) {
|
||||||
auth = await GoogleActions.authCheck(req.account, res, false)
|
auth = await GoogleActions.authCheck(req.account, res, false);
|
||||||
|
|
||||||
googleCount = await GoogleActions.listGoogleBrews(auth)
|
googleCount = await GoogleActions.listGoogleBrews(auth)
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
@@ -448,8 +516,6 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
|||||||
return next();
|
return next();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const nodeEnv = config.get('node_env');
|
|
||||||
const isLocalEnvironment = config.get('local_environments').includes(nodeEnv);
|
|
||||||
// Local only
|
// Local only
|
||||||
if(isLocalEnvironment){
|
if(isLocalEnvironment){
|
||||||
// Login
|
// Login
|
||||||
@@ -477,8 +543,8 @@ app.get('/vault', asyncHandler(async(req, res, next)=>{
|
|||||||
|
|
||||||
//Send rendered page
|
//Send rendered page
|
||||||
app.use(asyncHandler(async (req, res, next)=>{
|
app.use(asyncHandler(async (req, res, next)=>{
|
||||||
if (!req.route) return res.redirect('/'); // Catch-all for invalid routes
|
if(!req.route) return res.redirect('/'); // Catch-all for invalid routes
|
||||||
|
|
||||||
const page = await renderPage(req, res);
|
const page = await renderPage(req, res);
|
||||||
if(!page) return;
|
if(!page) return;
|
||||||
res.send(page);
|
res.send(page);
|
||||||
|
|||||||
@@ -467,12 +467,11 @@ const api = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
router.use('/api', checkClientVersion);
|
router.post('/api', checkClientVersion, asyncHandler(api.newBrew));
|
||||||
router.post('/api', asyncHandler(api.newBrew));
|
router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
||||||
router.put('/api/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
||||||
router.put('/api/update/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
|
router.delete('/api/:id', checkClientVersion, asyncHandler(api.deleteBrew));
|
||||||
router.delete('/api/:id', asyncHandler(api.deleteBrew));
|
router.get('/api/remove/:id', checkClientVersion, asyncHandler(api.deleteBrew));
|
||||||
router.get('/api/remove/:id', asyncHandler(api.deleteBrew));
|
|
||||||
router.get('/api/theme/:renderer/:id', asyncHandler(api.getThemeBundle));
|
router.get('/api/theme/:renderer/:id', asyncHandler(api.getThemeBundle));
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import packageJSON from '../../package.json' with { type: "json" };
|
import packageJSON from '../../package.json' with { type: 'json' };
|
||||||
const version = packageJSON.version;
|
|
||||||
|
|
||||||
export default (req, res, next)=>{
|
export default (req, res, next)=>{
|
||||||
const userVersion = req.get('Homebrewery-Version');
|
const userVersion = req.get('Homebrewery-Version');
|
||||||
|
const version = packageJSON.version;
|
||||||
|
|
||||||
if(userVersion != version) {
|
if(userVersion !== version) {
|
||||||
return res.status(412).send({
|
return res.status(412).send({
|
||||||
message : `Client version ${userVersion} is out of date. Please save your changes elsewhere and refresh to pick up client version ${version}.`
|
message : `Client version ${userVersion} is out of date. Please save your changes elsewhere and refresh to pick up client version ${version}.`
|
||||||
});
|
});
|
||||||
@@ -12,3 +12,4 @@ export default (req, res, next)=>{
|
|||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user