mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-27 09:33:08 +00:00
Compare commits
40 Commits
v3.15.0
...
v3.15.2ABC
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10d4cd4ab3 | ||
|
|
2a523c4955 | ||
|
|
487a574f50 | ||
|
|
1a325fb3c5 | ||
|
|
0110c6afed | ||
|
|
0e29620710 | ||
|
|
c33b44855a | ||
|
|
e7e35294c6 | ||
|
|
e9c45b216c | ||
|
|
40925253bd | ||
|
|
66433d9e77 | ||
|
|
3a6750613b | ||
|
|
a7361f8450 | ||
|
|
32fa272947 | ||
|
|
68895bdca2 | ||
|
|
8ab6a8599d | ||
|
|
ea656e5119 | ||
|
|
05ad8e17a7 | ||
|
|
bf87225415 | ||
|
|
8b61e69b77 | ||
|
|
e260eb0911 | ||
|
|
c8424e0b10 | ||
|
|
ff9a75f6b6 | ||
|
|
84736980c9 | ||
|
|
e0be7a5db3 | ||
|
|
2e332d7699 | ||
|
|
53979f2266 | ||
|
|
780c92cb9b | ||
|
|
20c54ef79e | ||
|
|
5ce69041fc | ||
|
|
20db8c6720 | ||
|
|
ed35eb2680 | ||
|
|
2a7b7cd50c | ||
|
|
d37fa03ec7 | ||
|
|
2c7d39147d | ||
|
|
6535e94ccd | ||
|
|
dd5d551c73 | ||
|
|
aa90513825 | ||
|
|
8f18601c2e | ||
|
|
db02f88287 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1 +1,3 @@
|
|||||||
package-lock.json binary
|
package-lock.json binary
|
||||||
|
|
||||||
|
*.json text eol=lf
|
||||||
@@ -4,7 +4,7 @@ const _ = require('lodash');
|
|||||||
|
|
||||||
import Dialog from '../../../components/dialog.jsx';
|
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 DISMISS_BUTTON = <i className='fas fa-times dismiss' />;
|
||||||
|
|
||||||
const NotificationPopup = ()=>{
|
const NotificationPopup = ()=>{
|
||||||
@@ -15,6 +15,34 @@ const NotificationPopup = ()=>{
|
|||||||
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
|
<small>This website is always improving and we are still adding new features and squashing bugs. Keep the following in mind:</small>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li key='ThrottlingError' style={{
|
||||||
|
backgroundColor: '#910000',
|
||||||
|
margin: '-10px -10px -10px -20px',
|
||||||
|
padding: '10px 10px 10px 20px',
|
||||||
|
fontSize: '1.0em'
|
||||||
|
}}>
|
||||||
|
<em>Known issue with saving/creating Google Drive files</em><br />
|
||||||
|
Dear users. The <a href="https://github.com/naturalcrit/homebrewery/issues/3770">
|
||||||
|
issue with saving to Google Drive</a> has resurfaced as of Oct 1, 2024 22:00 UTC.
|
||||||
|
<br></br><br></br>
|
||||||
|
Earlier we submitted a bug report to Google and have all but confirmed the issue
|
||||||
|
lies on Google's end and the disruption has been affecting multiple other
|
||||||
|
organizations besides us. Unfortunately, it means reliable interaction with
|
||||||
|
Google remains out of our control until they can resolve their issue.
|
||||||
|
<br></br><br></br>
|
||||||
|
Brews saved to Google Drive are <em>not lost</em> and can still be viewed, just not updated.
|
||||||
|
You can also access them via your Google Drive interface in the <code>/Hombrewery</code> folder.
|
||||||
|
<br></br><br></br>
|
||||||
|
If you need to urgently edit documents, you can detatch them from your Google Drive
|
||||||
|
by transferring them to our Homebrewery storage. To do this, click the colored Google Drive
|
||||||
|
icon next to the save button when on an edit page; you can transfer them back later,
|
||||||
|
but this should allow you to edit while this issue is ongoing.
|
||||||
|
<br></br><br></br>
|
||||||
|
If you are experiencing errors creating new documents, you can similarly change your
|
||||||
|
account settings to create new brews by default in the Homebrewery storage. Click
|
||||||
|
your username and then "account", then change the "default save location".
|
||||||
|
</li>
|
||||||
|
|
||||||
<li key='Vault'>
|
<li key='Vault'>
|
||||||
<em>Search brews with our new page!</em><br />
|
<em>Search brews with our new page!</em><br />
|
||||||
We have been working very hard in making this possible, now you can share your work and look at it in the new <a href="/vault">Vault</a> page!
|
We have been working very hard in making this possible, now you can share your work and look at it in the new <a href="/vault">Vault</a> page!
|
||||||
|
|||||||
@@ -116,6 +116,17 @@ const ErrorNavItem = createClass({
|
|||||||
</Nav.item>;
|
</Nav.item>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(HBErrorCode === '55') {
|
||||||
|
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
||||||
|
Oops!
|
||||||
|
<div className='errorContainer' onClick={clearError}>
|
||||||
|
Looks like there are too many requests
|
||||||
|
from this IP address in a short time.
|
||||||
|
Please try again after a few minutes.
|
||||||
|
</div>
|
||||||
|
</Nav.item>;
|
||||||
|
}
|
||||||
|
|
||||||
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
|
||||||
Oops!
|
Oops!
|
||||||
<div className='errorContainer'>
|
<div className='errorContainer'>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const RecentItems = createClass({
|
|||||||
//== Add current brew to appropriate recent items list (depending on storageKey) ==//
|
//== Add current brew to appropriate recent items list (depending on storageKey) ==//
|
||||||
if(this.props.storageKey == 'edit'){
|
if(this.props.storageKey == 'edit'){
|
||||||
let editId = this.props.brew.editId;
|
let editId = this.props.brew.editId;
|
||||||
if(this.props.brew.googleId){
|
if(this.props.brew.googleId && !this.props.brew.stubbed){
|
||||||
editId = `${this.props.brew.googleId}${this.props.brew.editId}`;
|
editId = `${this.props.brew.googleId}${this.props.brew.editId}`;
|
||||||
}
|
}
|
||||||
edited = _.filter(edited, (brew)=>{
|
edited = _.filter(edited, (brew)=>{
|
||||||
@@ -51,7 +51,7 @@ const RecentItems = createClass({
|
|||||||
}
|
}
|
||||||
if(this.props.storageKey == 'view'){
|
if(this.props.storageKey == 'view'){
|
||||||
let shareId = this.props.brew.shareId;
|
let shareId = this.props.brew.shareId;
|
||||||
if(this.props.brew.googleId){
|
if(this.props.brew.googleId && !this.props.brew.stubbed){
|
||||||
shareId = `${this.props.brew.googleId}${this.props.brew.shareId}`;
|
shareId = `${this.props.brew.googleId}${this.props.brew.shareId}`;
|
||||||
}
|
}
|
||||||
viewed = _.filter(viewed, (brew)=>{
|
viewed = _.filter(viewed, (brew)=>{
|
||||||
@@ -83,7 +83,7 @@ const RecentItems = createClass({
|
|||||||
let edited = JSON.parse(localStorage.getItem(EDIT_KEY) || '[]');
|
let edited = JSON.parse(localStorage.getItem(EDIT_KEY) || '[]');
|
||||||
if(this.props.storageKey == 'edit') {
|
if(this.props.storageKey == 'edit') {
|
||||||
let prevEditId = prevProps.brew.editId;
|
let prevEditId = prevProps.brew.editId;
|
||||||
if(prevProps.brew.googleId){
|
if(prevProps.brew.googleId && !this.props.brew.stubbed){
|
||||||
prevEditId = `${prevProps.brew.googleId}${prevProps.brew.editId}`;
|
prevEditId = `${prevProps.brew.googleId}${prevProps.brew.editId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ const RecentItems = createClass({
|
|||||||
return brew.id !== prevEditId;
|
return brew.id !== prevEditId;
|
||||||
});
|
});
|
||||||
let editId = this.props.brew.editId;
|
let editId = this.props.brew.editId;
|
||||||
if(this.props.brew.googleId){
|
if(this.props.brew.googleId && !this.props.brew.stubbed){
|
||||||
editId = `${this.props.brew.googleId}${this.props.brew.editId}`;
|
editId = `${this.props.brew.googleId}${this.props.brew.editId}`;
|
||||||
}
|
}
|
||||||
edited.unshift({
|
edited.unshift({
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const { printCurrentBrew, fetchThemeBundle } = require('../../../../shared/helpe
|
|||||||
|
|
||||||
const googleDriveIcon = require('../../googleDrive.svg');
|
const googleDriveIcon = require('../../googleDrive.svg');
|
||||||
|
|
||||||
const SAVE_TIMEOUT = 3000;
|
const SAVE_TIMEOUT = 16000;
|
||||||
|
|
||||||
const EditPage = createClass({
|
const EditPage = createClass({
|
||||||
displayName : 'EditPage',
|
displayName : 'EditPage',
|
||||||
|
|||||||
@@ -1,7 +1,22 @@
|
|||||||
body {
|
.vaultPage {
|
||||||
height : 100vh;
|
height : 100%;
|
||||||
|
overflow-y : hidden;
|
||||||
|
background-color : #2C3E50;
|
||||||
|
|
||||||
.content { height : 100%; }
|
*:not(input) { user-select : none; }
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background : #2C3E50;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.dataGroup {
|
||||||
|
width : 100%;
|
||||||
|
height : 100%;
|
||||||
|
background : white;
|
||||||
|
|
||||||
|
&.form .brewLookup {
|
||||||
|
position : relative;
|
||||||
|
padding : 50px clamp(20px, 4vw, 50px);
|
||||||
|
|
||||||
small {
|
small {
|
||||||
font-size : 10pt;
|
font-size : 10pt;
|
||||||
@@ -14,35 +29,14 @@ body {
|
|||||||
padding-inline : 5px;
|
padding-inline : 5px;
|
||||||
background : lightgrey;
|
background : lightgrey;
|
||||||
border-radius : 5px;
|
border-radius : 5px;
|
||||||
|
font-family : monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
*:not(input) { user-select : none; }
|
|
||||||
}
|
|
||||||
|
|
||||||
.vaultPage {
|
|
||||||
height : 100%;
|
|
||||||
overflow-y : hidden;
|
|
||||||
background-color : #2C3E50;
|
|
||||||
|
|
||||||
|
|
||||||
.content {
|
|
||||||
background : #2C3E50;
|
|
||||||
|
|
||||||
.dataGroup {
|
|
||||||
width : 100%;
|
|
||||||
height : 100%;
|
|
||||||
background : white;
|
|
||||||
|
|
||||||
&.form .brewLookup {
|
|
||||||
position : relative;
|
|
||||||
padding : 50px clamp(20px, 4vw, 50px);
|
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
h1, h2, h3, h4 {
|
||||||
font-family : 'CodeBold';
|
font-family : 'CodeBold';
|
||||||
letter-spacing : 2px;
|
letter-spacing : 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
h3 {
|
h3 {
|
||||||
margin-block : 30px 20px;
|
margin-block : 30px 20px;
|
||||||
@@ -144,8 +138,6 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#searchButton {
|
#searchButton {
|
||||||
position : absolute;
|
position : absolute;
|
||||||
right : 20px;
|
right : 20px;
|
||||||
@@ -167,7 +159,6 @@ body {
|
|||||||
font-family : 'BookInsanityRemake';
|
font-family : 'BookInsanityRemake';
|
||||||
font-size : 0.34cm;
|
font-size : 0.34cm;
|
||||||
|
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-family : 'Open Sans';
|
font-family : 'Open Sans';
|
||||||
font-weight : 900;
|
font-weight : 900;
|
||||||
|
|||||||
40
package-lock.json
generated
40
package-lock.json
generated
@@ -25,6 +25,7 @@
|
|||||||
"expr-eval": "^2.0.2",
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
|
"express-rate-limit": "^7.4.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "11.2.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@@ -38,7 +39,7 @@
|
|||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.6.0",
|
"mongoose": "^8.6.1",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@@ -52,8 +53,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-jest": "^28.8.2",
|
"eslint-plugin-jest": "^28.8.3",
|
||||||
"eslint-plugin-react": "^7.35.1",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
@@ -5878,9 +5879,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-jest": {
|
"node_modules/eslint-plugin-jest": {
|
||||||
"version": "28.8.2",
|
"version": "28.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.8.3.tgz",
|
||||||
"integrity": "sha512-mC3OyklHmS5i7wYU1rGId9EnxRI8TVlnFG56AE+8U9iRy6zwaNygZR+DsdZuCL0gRG0wVeyzq+uWcPt6yJrrMA==",
|
"integrity": "sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
@@ -5903,9 +5904,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-react": {
|
"node_modules/eslint-plugin-react": {
|
||||||
"version": "7.35.1",
|
"version": "7.35.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz",
|
||||||
"integrity": "sha512-B5ok2JgbaaWn/zXbKCGgKDNL2tsID3Pd/c/yvjcpsd9HQDwyYc/TQv3AZMmOvrJgCs3AnYNUHRCQEMMQAYJ7Yg==",
|
"integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"array-includes": "^3.1.8",
|
"array-includes": "^3.1.8",
|
||||||
@@ -6352,6 +6353,21 @@
|
|||||||
"integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==",
|
"integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/express-rate-limit": {
|
||||||
|
"version": "7.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.0.tgz",
|
||||||
|
"integrity": "sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/express-rate-limit"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"express": "4 || 5 || ^5.0.0-beta.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/express-static-gzip": {
|
"node_modules/express-static-gzip": {
|
||||||
"version": "2.1.7",
|
"version": "2.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.7.tgz",
|
||||||
@@ -10794,9 +10810,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose": {
|
"node_modules/mongoose": {
|
||||||
"version": "8.6.0",
|
"version": "8.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.6.1.tgz",
|
||||||
"integrity": "sha512-p6VSbYKvD4ZIabqo8C0kS5eKX1Xpji+opTAIJ9wyuPJ8Y/FblgXSMnFRXnB40bYZLKPQT089K5KU8+bqIXtFdw==",
|
"integrity": "sha512-dppGcYqvsdg+VcnqXR5b467V4a+iNhmvkfYNpEPi6AjaUxnz6ioEDmrMLOi+sOWjvoHapuwPOigV4f2l7HC6ag==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bson": "^6.7.0",
|
"bson": "^6.7.0",
|
||||||
"kareem": "2.6.3",
|
"kareem": "2.6.3",
|
||||||
|
|||||||
@@ -100,6 +100,7 @@
|
|||||||
"expr-eval": "^2.0.2",
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
|
"express-rate-limit": "^7.4.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "11.2.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@@ -113,7 +114,7 @@
|
|||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.6.0",
|
"mongoose": "^8.6.1",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
@@ -127,8 +128,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.9.1",
|
||||||
"eslint-plugin-jest": "^28.8.2",
|
"eslint-plugin-jest": "^28.8.3",
|
||||||
"eslint-plugin-react": "^7.35.1",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ const sanitizeBrew = (brew, accessType)=>{
|
|||||||
return brew;
|
return brew;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
app.set('trust proxy', 1 /* number of proxies between user and server */)
|
||||||
|
app.get('/ip', (request, response) => response.send(request.ip))
|
||||||
|
|
||||||
|
|
||||||
app.use('/', serveCompressedStaticAssets(`build`));
|
app.use('/', serveCompressedStaticAssets(`build`));
|
||||||
app.use(require('./middleware/content-negotiation.js'));
|
app.use(require('./middleware/content-negotiation.js'));
|
||||||
app.use(require('body-parser').json({ limit: '25mb' }));
|
app.use(require('body-parser').json({ limit: '25mb' }));
|
||||||
@@ -238,6 +242,8 @@ 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"
|
||||||
|
|
||||||
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);
|
||||||
let googleBrews = await GoogleActions.listGoogleBrews(auth)
|
let googleBrews = await GoogleActions.listGoogleBrews(auth)
|
||||||
@@ -245,12 +251,12 @@ app.get('/user/:username', async (req, res, next)=>{
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If stub matches file from Google, use Google metadata over stub metadata
|
||||||
if(googleBrews && googleBrews.length > 0) {
|
if(googleBrews && googleBrews.length > 0) {
|
||||||
for (const brew of brews.filter((brew)=>brew.googleId)) {
|
for (const brew of brews.filter((brew)=>brew.googleId)) {
|
||||||
const match = googleBrews.findIndex((b)=>b.editId === brew.editId);
|
const match = googleBrews.findIndex((b)=>b.editId === brew.editId);
|
||||||
if(match !== -1) {
|
if(match !== -1) {
|
||||||
brew.googleId = googleBrews[match].googleId;
|
brew.googleId = googleBrews[match].googleId;
|
||||||
brew.stubbed = true;
|
|
||||||
brew.pageCount = googleBrews[match].pageCount;
|
brew.pageCount = googleBrews[match].pageCount;
|
||||||
brew.renderer = googleBrews[match].renderer;
|
brew.renderer = googleBrews[match].renderer;
|
||||||
brew.version = googleBrews[match].version;
|
brew.version = googleBrews[match].version;
|
||||||
@@ -259,6 +265,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] }));
|
googleBrews = googleBrews.map((brew)=>({ ...brew, authors: [req.account.username] }));
|
||||||
brews = _.concat(brews, googleBrews);
|
brews = _.concat(brews, googleBrews);
|
||||||
}
|
}
|
||||||
@@ -375,22 +382,12 @@ 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) {
|
||||||
try {
|
auth = await GoogleActions.authCheck(req.account, res, false)
|
||||||
auth = await GoogleActions.authCheck(req.account, res, false);
|
|
||||||
} catch (e) {
|
googleCount = await GoogleActions.listGoogleBrews(auth)
|
||||||
auth = undefined;
|
.catch((err)=>{
|
||||||
console.log('Google auth check failed!');
|
console.error(err);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = { authors: req.account.username, googleId: { $exists: false } };
|
const query = { authors: req.account.username, googleId: { $exists: false } };
|
||||||
@@ -404,7 +401,7 @@ app.get('/account', asyncHandler(async (req, res, next)=>{
|
|||||||
username : req.account.username,
|
username : req.account.username,
|
||||||
issued : req.account.issued,
|
issued : req.account.issued,
|
||||||
googleId : Boolean(req.account.googleId),
|
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,
|
mongoCount : mongoCount,
|
||||||
googleCount : googleCount?.length
|
googleCount : googleCount?.length
|
||||||
};
|
};
|
||||||
@@ -498,7 +495,7 @@ app.use(async (err, req, res, next)=>{
|
|||||||
err.originalUrl = req.originalUrl;
|
err.originalUrl = req.originalUrl;
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
if(err.originalUrl?.startsWith('/api/')) {
|
if(err.originalUrl?.startsWith('/api')) {
|
||||||
// console.log('API error');
|
// console.log('API error');
|
||||||
res.status(err.status || err.response?.status || 500).send(err);
|
res.status(err.status || err.response?.status || 500).send(err);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -25,6 +25,15 @@ if(!config.get('service_account')){
|
|||||||
|
|
||||||
const defaultAuth = serviceAuth || config.get('google_api_key');
|
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 = {
|
const GoogleActions = {
|
||||||
|
|
||||||
authCheck : (account, res, updateTokens=true)=>{
|
authCheck : (account, res, updateTokens=true)=>{
|
||||||
@@ -112,9 +121,7 @@ const GoogleActions = {
|
|||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log(`Error Listing Google Brews`);
|
console.log(`Error Listing Google Brews`);
|
||||||
console.error(err);
|
|
||||||
throw (err);
|
throw (err);
|
||||||
//TODO: Should break out here, but continues on for some reason.
|
|
||||||
});
|
});
|
||||||
fileList.push(...obj.data.files);
|
fileList.push(...obj.data.files);
|
||||||
NextPageToken = obj.data.nextPageToken;
|
NextPageToken = obj.data.nextPageToken;
|
||||||
@@ -147,8 +154,9 @@ const GoogleActions = {
|
|||||||
return brews;
|
return brews;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateGoogleBrew : async (brew)=>{
|
updateGoogleBrew : async (brew, auth = defaultAuth, userIp)=>{
|
||||||
const drive = googleDrive.drive({ version: 'v3', auth: defaultAuth });
|
const drive = googleDrive.drive({ version: 'v3', auth: auth });
|
||||||
|
console.log(auth == defaultAuth ? 'UPDATE w SERVICEACC' : 'UPDATE w USERACC')
|
||||||
|
|
||||||
await drive.files.update({
|
await drive.files.update({
|
||||||
fileId : brew.googleId,
|
fileId : brew.googleId,
|
||||||
@@ -168,11 +176,14 @@ const GoogleActions = {
|
|||||||
media : {
|
media : {
|
||||||
mimeType : 'text/plain',
|
mimeType : 'text/plain',
|
||||||
body : brew.text
|
body : brew.text
|
||||||
}
|
},
|
||||||
|
headers: {
|
||||||
|
'X-Forwarded-For': userIp, // Set the X-Forwarded-For header
|
||||||
|
},
|
||||||
|
retryConfig
|
||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log('Error saving to google');
|
console.log('Error saving to google');
|
||||||
console.error(err);
|
|
||||||
throw (err);
|
throw (err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const yaml = require('js-yaml');
|
|||||||
const asyncHandler = require('express-async-handler');
|
const asyncHandler = require('express-async-handler');
|
||||||
const { nanoid } = require('nanoid');
|
const { nanoid } = require('nanoid');
|
||||||
const { splitTextStyleAndMetadata } = require('../shared/helpers.js');
|
const { splitTextStyleAndMetadata } = require('../shared/helpers.js');
|
||||||
|
const rateLimit = require('express-rate-limit');
|
||||||
|
|
||||||
const { DEFAULT_BREW, DEFAULT_BREW_LOAD } = require('./brewDefaults.js');
|
const { DEFAULT_BREW, DEFAULT_BREW_LOAD } = require('./brewDefaults.js');
|
||||||
|
|
||||||
@@ -242,11 +243,8 @@ const api = {
|
|||||||
|
|
||||||
let googleId, saved;
|
let googleId, saved;
|
||||||
if(saveToGoogle) {
|
if(saveToGoogle) {
|
||||||
googleId = await api.newGoogleBrew(req.account, newHomebrew, res)
|
googleId = await api.newGoogleBrew(req.account, newHomebrew, res);
|
||||||
.catch((err)=>{
|
|
||||||
console.error(err);
|
|
||||||
res.status(err?.status || err?.response?.status || 500).send(err?.message || err);
|
|
||||||
});
|
|
||||||
if(!googleId) return;
|
if(!googleId) return;
|
||||||
api.excludeStubProps(newHomebrew);
|
api.excludeStubProps(newHomebrew);
|
||||||
newHomebrew.googleId = googleId;
|
newHomebrew.googleId = googleId;
|
||||||
@@ -351,19 +349,13 @@ const api = {
|
|||||||
brew.googleId = undefined;
|
brew.googleId = undefined;
|
||||||
} else if(!brew.googleId && saveToGoogle) {
|
} else if(!brew.googleId && saveToGoogle) {
|
||||||
// If we don't have a google id and the user wants to save to google, create the google brew and set the google id on the brew
|
// If we don't have a google id and the user wants to save to google, create the google brew and set the google id on the brew
|
||||||
brew.googleId = await api.newGoogleBrew(req.account, api.excludeGoogleProps(brew), res)
|
brew.googleId = await api.newGoogleBrew(req.account, api.excludeGoogleProps(brew), res);
|
||||||
.catch((err)=>{
|
|
||||||
console.error(err);
|
|
||||||
res.status(err.status || err.response.status).send(err.message || err);
|
|
||||||
});
|
|
||||||
if(!brew.googleId) return;
|
if(!brew.googleId) return;
|
||||||
} else if(brew.googleId) {
|
} else if(brew.googleId) {
|
||||||
// If the google id exists and no other actions are being performed, update the google brew
|
// 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 api.updateGoogleBrew(req.account, api.excludeGoogleProps(brew), res, req);
|
||||||
.catch((err)=>{
|
|
||||||
console.error(err);
|
|
||||||
res.status(err?.response?.status || 500).send(err);
|
|
||||||
});
|
|
||||||
if(!updated) return;
|
if(!updated) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,6 +398,15 @@ const api = {
|
|||||||
|
|
||||||
res.status(200).send(saved);
|
res.status(200).send(saved);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateGoogleBrew : async (account, brew, res, req)=>{
|
||||||
|
//let oAuth2Client;
|
||||||
|
//if(account.googleId)
|
||||||
|
// oAuth2Client = GoogleActions.authCheck(account, res);
|
||||||
|
|
||||||
|
return await GoogleActions.updateGoogleBrew(brew, undefined, req.ip);
|
||||||
|
},
|
||||||
|
|
||||||
deleteGoogleBrew : async (account, id, editId, res)=>{
|
deleteGoogleBrew : async (account, id, editId, res)=>{
|
||||||
const auth = await GoogleActions.authCheck(account, res);
|
const auth = await GoogleActions.authCheck(account, res);
|
||||||
await GoogleActions.deleteGoogleBrew(auth, id, editId);
|
await GoogleActions.deleteGoogleBrew(auth, id, editId);
|
||||||
|
|||||||
@@ -560,16 +560,6 @@ brew`);
|
|||||||
views : 0
|
views : 0
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle google error', async()=>{
|
|
||||||
google.newGoogleBrew = jest.fn(()=>{
|
|
||||||
throw 'err';
|
|
||||||
});
|
|
||||||
await api.newBrew({ body: { text: 'asdf', title: '' }, query: { saveToGoogle: true }, account: { username: 'test user' } }, res);
|
|
||||||
|
|
||||||
expect(res.status).toHaveBeenCalledWith(500);
|
|
||||||
expect(res.send).toHaveBeenCalledWith('err');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deleteGoogleBrew', ()=>{
|
describe('deleteGoogleBrew', ()=>{
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ const SplitPane = createClass({
|
|||||||
windowWidth : 0,
|
windowWidth : 0,
|
||||||
isDragging : false,
|
isDragging : false,
|
||||||
moveSource : false,
|
moveSource : false,
|
||||||
moveBrew : false
|
moveBrew : false,
|
||||||
|
showMoveArrows : true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user