mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-26 09:32:51 +00:00
iMerge branch 'master' of github.com:naturalcrit/homebrewery
This commit is contained in:
76
changelog.md
76
changelog.md
@@ -81,9 +81,85 @@ pre {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## changelog
|
||||
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
|
||||
|
||||
### Saturday 10/12/2024 - v3.16.0
|
||||
|
||||
{{taskList
|
||||
##### 5e-Cleric
|
||||
|
||||
* [x] Added a new API endpoint `/metadata/:shareId` to fetch metadata about individual brews
|
||||
|
||||
Fixes issue [#2638](https://github.com/naturalcrit/homebrewery/issues/2638)
|
||||
|
||||
* [x] Added A3, A5, and Card page size snippets under {{openSans **:fas_paintbrush: STYLE TAB :fas_arrow_right: :fas_print: PRINT**}}
|
||||
|
||||
* [x] Adjust navbar styling for very long titles
|
||||
|
||||
Fixes issue [#2071](https://github.com/naturalcrit/homebrewery/issues/2071)
|
||||
|
||||
* [x] Added some sorting options to the {{openSans **VAULT** {{fas,fa-dungeon}}}} page
|
||||
|
||||
* [x] Fix `language` property not working in share page
|
||||
|
||||
Fixes issue [#3776](https://github.com/naturalcrit/homebrewery/issues/3776)
|
||||
|
||||
##### abquintic
|
||||
|
||||
* [x] New {{openSans **:fas_pencil: TEXT EDITOR :fas_arrow_right: :fas_bookmark: PAGE NUMBER :fas_arrow_right:**}}
|
||||
{{openSans **:fas_xmark: SKIP PAGE NUMBER**}} and {{openSans **:fas_arrow_rotate_left: RESTART PAGE NUMBER**}} snippets for more control over automatic page numbering.
|
||||
|
||||
Fixes issue [#513](https://github.com/naturalcrit/homebrewery/issues/513)
|
||||
|
||||
* [x] New Table of Contents control options via {{openSans **:fas_pencil: TEXT EDITOR :fas_arrow_right: :fas_book: TABLE OF CONTENTS**}} submenus. By default, H1-H3 is included in the ToC generation, but the new options allow marking `{{blocks}}` to include or exclude specific or ranges of contained headers. Also, a global option to increase the default range of H1-H3 to H1-H4/5/6. After applying these markers, you must regenerate the Table of Contents to see the changes.
|
||||
|
||||
* [x] Added a ":fas_lock: SYNC VIEWS" button onto the divider bar. When locked, scrolling on either panel will sync the other panel to the same page.
|
||||
|
||||
Fixes issue [#241](https://github.com/naturalcrit/homebrewery/issues/241)
|
||||
|
||||
##### Gazook89
|
||||
|
||||
* [x] Added a :fas_glasses: HIDE button to the page navigation bar
|
||||
|
||||
##### G-Ambatte
|
||||
|
||||
* [x] Automatic local backups of your files, in case of accidental data loss. Stores up to 5 snapshots of each brew edited in your browser, incrementing from a few minutes old to a maximum of several days. Restore a backup by clicking an entry in the new {{openSans **:fas_clock_rotate_left: HISTORY**}} button in the snippet bar.
|
||||
|
||||
Fixes issue [#3070](https://github.com/naturalcrit/homebrewery/issues/3070)
|
||||
|
||||
* [x] Fix issue with legacy brews breaking on Share page
|
||||
|
||||
Fixes issue [#3764](https://github.com/naturalcrit/homebrewery/issues/3764)
|
||||
|
||||
* [x] Fix print size when printing a zoomed document
|
||||
|
||||
Fixes issue [#3744](https://github.com/naturalcrit/homebrewery/issues/3744)
|
||||
|
||||
##### All
|
||||
|
||||
* [x] Background code cleanup, security fixes, dev tool improvements, dependency updates, prep for upcoming features, etc.
|
||||
}}
|
||||
|
||||
### Wednesday 9/25/2024 - v3.15.1
|
||||
|
||||
{{taskList
|
||||
##### calculuschild
|
||||
|
||||
* [x] Background fixes to handle Google Drive issues
|
||||
|
||||
* [x] Remove duplicate error logging
|
||||
|
||||
##### calculuschild, 5e-Cleric
|
||||
|
||||
* [x] Fix links in {{openSans **RECENT BREWS :fas_clock_rotate_left:**}} and user {{openSans **BREWS :fas_beer_mug_empty:**}} pointing to trashed Google Drive files after transferring from Google to Homebrewery storage
|
||||
|
||||
Fixes issue [#3776](https://github.com/naturalcrit/homebrewery/issues/3776)
|
||||
}}
|
||||
|
||||
\page
|
||||
|
||||
### Wednesday 9/04/2024 - v3.15.0
|
||||
|
||||
{{taskList
|
||||
|
||||
@@ -4,7 +4,7 @@ const _ = require('lodash');
|
||||
|
||||
import Dialog from '../../../components/dialog.jsx';
|
||||
|
||||
const DISMISS_KEY = 'dismiss_notification04-09-24';
|
||||
const DISMISS_KEY = 'dismiss_notification01-10-24';
|
||||
const DISMISS_BUTTON = <i className='fas fa-times dismiss' />;
|
||||
|
||||
const NotificationPopup = ()=>{
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "homebrewery",
|
||||
"version": "3.15.0",
|
||||
"version": "3.16.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "homebrewery",
|
||||
"version": "3.15.0",
|
||||
"version": "3.16.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "homebrewery",
|
||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||
"version": "3.15.0",
|
||||
"version": "3.16.0",
|
||||
"engines": {
|
||||
"npm": "^10.2.x",
|
||||
"node": "^20.17.x"
|
||||
|
||||
@@ -10,7 +10,6 @@ const app = express();
|
||||
const config = require('./config.js');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
|
||||
const { homebrewApi, getBrew, getUsersBrewThemes, getCSS } = require('./homebrew.api.js');
|
||||
const GoogleActions = require('./googleActions.js');
|
||||
const serveCompressedStaticAssets = require('./static-assets.mv.js');
|
||||
@@ -32,6 +31,8 @@ const sanitizeBrew = (brew, accessType)=>{
|
||||
return brew;
|
||||
};
|
||||
|
||||
app.set('trust proxy', 1 /* number of proxies between user and server */)
|
||||
|
||||
app.use('/', serveCompressedStaticAssets(`build`));
|
||||
app.use(require('./middleware/content-negotiation.js'));
|
||||
app.use(require('body-parser').json({ limit: '25mb' }));
|
||||
@@ -257,6 +258,8 @@ app.get('/user/:username', async (req, res, next)=>{
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
brews.forEach(brew => brew.stubbed = true); //All brews from MongoDB are "stubbed"
|
||||
|
||||
if(ownAccount && req?.account?.googleId){
|
||||
const auth = await GoogleActions.authCheck(req.account, res);
|
||||
let googleBrews = await GoogleActions.listGoogleBrews(auth)
|
||||
@@ -264,12 +267,12 @@ app.get('/user/:username', async (req, res, next)=>{
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
// If stub matches file from Google, use Google metadata over stub metadata
|
||||
if(googleBrews && googleBrews.length > 0) {
|
||||
for (const brew of brews.filter((brew)=>brew.googleId)) {
|
||||
const match = googleBrews.findIndex((b)=>b.editId === brew.editId);
|
||||
if(match !== -1) {
|
||||
brew.googleId = googleBrews[match].googleId;
|
||||
brew.stubbed = true;
|
||||
brew.pageCount = googleBrews[match].pageCount;
|
||||
brew.renderer = googleBrews[match].renderer;
|
||||
brew.version = googleBrews[match].version;
|
||||
@@ -278,6 +281,7 @@ app.get('/user/:username', async (req, res, next)=>{
|
||||
}
|
||||
}
|
||||
|
||||
//Remaining unstubbed google brews display current user as author
|
||||
googleBrews = googleBrews.map((brew)=>({ ...brew, authors: [req.account.username] }));
|
||||
brews = _.concat(brews, googleBrews);
|
||||
}
|
||||
@@ -380,7 +384,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r
|
||||
app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
const data = {};
|
||||
data.title = 'Account Information Page';
|
||||
|
||||
|
||||
if(!req.account) {
|
||||
res.set('WWW-Authenticate', 'Bearer realm="Authorization Required"');
|
||||
const error = new Error('No valid account');
|
||||
@@ -394,22 +398,12 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
let googleCount = [];
|
||||
if(req.account) {
|
||||
if(req.account.googleId) {
|
||||
try {
|
||||
auth = await GoogleActions.authCheck(req.account, res, false);
|
||||
} catch (e) {
|
||||
auth = undefined;
|
||||
console.log('Google auth check failed!');
|
||||
console.log(e);
|
||||
}
|
||||
if(auth.credentials.access_token) {
|
||||
try {
|
||||
googleCount = await GoogleActions.listGoogleBrews(auth);
|
||||
} catch (e) {
|
||||
googleCount = undefined;
|
||||
console.log('List Google files failed!');
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
auth = await GoogleActions.authCheck(req.account, res, false)
|
||||
|
||||
googleCount = await GoogleActions.listGoogleBrews(auth)
|
||||
.catch((err)=>{
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
const query = { authors: req.account.username, googleId: { $exists: false } };
|
||||
@@ -423,7 +417,7 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
||||
username : req.account.username,
|
||||
issued : req.account.issued,
|
||||
googleId : Boolean(req.account.googleId),
|
||||
authCheck : Boolean(req.account.googleId && auth.credentials.access_token),
|
||||
authCheck : Boolean(req.account.googleId && auth?.credentials.access_token),
|
||||
mongoCount : mongoCount,
|
||||
googleCount : googleCount?.length
|
||||
};
|
||||
@@ -468,8 +462,8 @@ app.get('/vault', asyncHandler(async(req, res, next)=>{
|
||||
|
||||
//Send rendered page
|
||||
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);
|
||||
if(!page) return;
|
||||
res.send(page);
|
||||
|
||||
@@ -25,6 +25,15 @@ if(!config.get('service_account')){
|
||||
|
||||
const defaultAuth = serviceAuth || config.get('google_api_key');
|
||||
|
||||
const retryConfig = {
|
||||
retry: 3, // Number of retry attempts
|
||||
retryDelay: 100, // Initial delay in milliseconds
|
||||
retryDelayMultiplier: 2, // Multiplier for exponential backoff
|
||||
maxRetryDelay: 32000, // Maximum delay in milliseconds
|
||||
httpMethodsToRetry: ['PATCH'], // Only retry PATCH requests
|
||||
statusCodesToRetry: [[429, 429]], // Only retry on 429 status code
|
||||
};
|
||||
|
||||
const GoogleActions = {
|
||||
|
||||
authCheck : (account, res, updateTokens=true)=>{
|
||||
@@ -112,9 +121,7 @@ const GoogleActions = {
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log(`Error Listing Google Brews`);
|
||||
console.error(err);
|
||||
throw (err);
|
||||
//TODO: Should break out here, but continues on for some reason.
|
||||
});
|
||||
fileList.push(...obj.data.files);
|
||||
NextPageToken = obj.data.nextPageToken;
|
||||
@@ -147,7 +154,7 @@ const GoogleActions = {
|
||||
return brews;
|
||||
},
|
||||
|
||||
updateGoogleBrew : async (brew)=>{
|
||||
updateGoogleBrew : async (brew, userIp)=>{
|
||||
const drive = googleDrive.drive({ version: 'v3', auth: defaultAuth });
|
||||
|
||||
await drive.files.update({
|
||||
@@ -168,7 +175,11 @@ const GoogleActions = {
|
||||
media : {
|
||||
mimeType : 'text/plain',
|
||||
body : brew.text
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
'X-Forwarded-For': userIp, // Set the X-Forwarded-For header
|
||||
},
|
||||
retryConfig
|
||||
})
|
||||
.catch((err)=>{
|
||||
console.log('Error saving to google');
|
||||
|
||||
@@ -353,7 +353,7 @@ const api = {
|
||||
if(!brew.googleId) return;
|
||||
} else if(brew.googleId) {
|
||||
// If the google id exists and no other actions are being performed, update the google brew
|
||||
const updated = await GoogleActions.updateGoogleBrew(api.excludeGoogleProps(brew));
|
||||
const updated = await GoogleActions.updateGoogleBrew(api.excludeGoogleProps(brew), req.ip);
|
||||
|
||||
if(!updated) return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user