diff --git a/.env.example b/.env.example
index 911a1e45..64c5ad79 100644
--- a/.env.example
+++ b/.env.example
@@ -3,6 +3,11 @@ MYSQL_USER=
MYSQL_PASS=
MYSQL_DB=
+REDIS_URL=
+REDIS_DB=
+REDIS_PREFIX="gs:"
+REDIS_AUTH=""
+
JWT_SECRET=
JWT_EXPIRY=86400
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f1fdafea..c43110a3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -30,7 +30,6 @@ build-react:
expire_in: 1 day
paths:
- web/build
- - web/public
- .env.example
bundle:
@@ -41,8 +40,8 @@ bundle:
before_script:
- apk add --no-cache zip tar
script:
- - zip -r goscrobble.zip web goscrobble migrations init .env.example
- - tar -czf goscrobble.tar.gz web goscrobble migrations init .env.example
+ - zip -r goscrobble.zip web/build goscrobble migrations init .env.example
+ - tar -czf goscrobble.tar.gz web/build goscrobble migrations init .env.example
artifacts:
expire_in: 6 months
paths:
diff --git a/README.md b/README.md
index fad570b6..4164e014 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,14 @@
# go-scrobble
-Golang based music scrobbler. MySQL 8.0+
+Golang based music scrobbler.
-Currently building on Node V15.X & Go V1.16.X
+Stack: Go 1.16+, Node 15+, React 17+, MySQL 8.0+, Redis
+
+There are prebuilt binaries/packages available.
-With a prebuilt binary - you will still need the migrations folder + web/build folder on prod.
Copy .env.example to .env and set variables. You can use https://www.grc.com/passwords.htm to generate a JWT_SECRET.
-
## Setup MySQL
create user 'goscrobble'@'%' identified by 'supersecurepass';
create database goscrobble;
@@ -31,4 +31,8 @@ We need to build NPM package, and then ship web/build with the binary.
cp .env.example .env # Fill in the blanks
cd web npm install --production && REACT_APP_API_URL=https://goscrobble.com npm run build
go build -o goscrobble cmd/go-scrobble/*.go
- ./goscrobble
\ No newline at end of file
+ ./goscrobble
+
+
+## Support Development!
+Feel free to support hosting and my coffee addiction https://liberapay.com/idanoo
\ No newline at end of file
diff --git a/docs/config.md b/docs/config.md
new file mode 100644
index 00000000..13ff35b0
--- /dev/null
+++ b/docs/config.md
@@ -0,0 +1,21 @@
+## FRONTEND VARS
+ REACT_APP_REGISTRATION_DISABLED=true // Disables registration
+ REACT_APP_API_URL=https://goscrobble.com // Sets API URL
+
+
+## BACKEND VARS
+ MYSQL_HOST= // MySQL Server
+ MYSQL_USER= // MySQL User
+ MYSQL_PASS= // MySQL Password
+ MYSQL_DB= // MySQL Database
+
+ REDIS_URL= // Redis host
+ REDIS_DB=4 // Redis DB
+ REDIS_PREFIX="gs:" // Redis key prefix
+ REDIS_AUTH="" // Redis password
+
+ JWT_SECRET= // 32+ Char JWT secret
+ JWT_EXPIRY=86400 // JWT expiry
+
+ REVERSE_PROXIES=127.0.0.1 // Comma separated list of servers to ignore for IP logs
+ PORT=42069 // Server port
\ No newline at end of file
diff --git a/web/package-lock.json b/web/package-lock.json
index 673548f3..664fceb3 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -13,8 +13,10 @@
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^12.8.3",
"bootstrap": "^4.6.0",
+ "formik": "^2.2.6",
"react": "^17.0.2",
"react-bootstrap": "^1.5.2",
+ "react-cookie": "^4.0.3",
"react-dom": "^17.0.2",
"react-redux": "^7.2.3",
"react-router-dom": "^5.2.0",
@@ -22,6 +24,7 @@
"react-toast": "^1.0.1",
"react-toast-notifications": "^2.4.3",
"reactstrap": "^8.9.0",
+ "redux-persist": "^6.0.0",
"web-vitals": "^1.1.1"
},
"devDependencies": {
@@ -3095,6 +3098,11 @@
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.11.tgz",
"integrity": "sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw=="
},
+ "node_modules/@types/cookie": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
+ "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
+ },
"node_modules/@types/eslint": {
"version": "7.2.7",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.7.tgz",
@@ -8961,6 +8969,42 @@
"node": ">= 0.12"
}
},
+ "node_modules/formik": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.6.tgz",
+ "integrity": "sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://opencollective.com/formik"
+ }
+ ],
+ "dependencies": {
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.14",
+ "lodash-es": "^4.17.14",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^1.10.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/formik/node_modules/deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/formik/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
"node_modules/forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -16241,6 +16285,19 @@
"regenerator-runtime": "^0.13.4"
}
},
+ "node_modules/react-cookie": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.0.3.tgz",
+ "integrity": "sha512-cmi6IpdVgTSvjqssqIEvo779Gfqc4uPGHRrKMEdHcqkmGtPmxolGfsyKj95bhdLEKqMdbX8MLBCwezlnhkHK0g==",
+ "dependencies": {
+ "@types/hoist-non-react-statics": "^3.0.1",
+ "hoist-non-react-statics": "^3.0.0",
+ "universal-cookie": "^4.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.3.0"
+ }
+ },
"node_modules/react-dev-utils": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz",
@@ -16357,6 +16414,11 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
},
+ "node_modules/react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -16862,6 +16924,14 @@
"symbol-observable": "^1.2.0"
}
},
+ "node_modules/redux-persist": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
+ "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
+ "peerDependencies": {
+ "redux": ">4.0.0"
+ }
+ },
"node_modules/redux-thunk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
@@ -19892,6 +19962,15 @@
"node": ">=4"
}
},
+ "node_modules/universal-cookie": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz",
+ "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==",
+ "dependencies": {
+ "@types/cookie": "^0.3.3",
+ "cookie": "^0.4.0"
+ }
+ },
"node_modules/universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
@@ -24453,6 +24532,11 @@
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.11.tgz",
"integrity": "sha512-2koNhpWm3DgWRp5tpkiJ8JGc1xTn2q0l+jUNUE7oMKXUf5NpI9AIdC4kbjGNFBdHtcxBD18LAksoudAVhFKCjw=="
},
+ "@types/cookie": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
+ "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
+ },
"@types/eslint": {
"version": "7.2.7",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.7.tgz",
@@ -29137,6 +29221,32 @@
"mime-types": "^2.1.12"
}
},
+ "formik": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.6.tgz",
+ "integrity": "sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA==",
+ "requires": {
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.14",
+ "lodash-es": "^4.17.14",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^1.10.0"
+ },
+ "dependencies": {
+ "deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
+ },
+ "tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ }
+ }
+ },
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -34782,6 +34892,16 @@
}
}
},
+ "react-cookie": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.0.3.tgz",
+ "integrity": "sha512-cmi6IpdVgTSvjqssqIEvo779Gfqc4uPGHRrKMEdHcqkmGtPmxolGfsyKj95bhdLEKqMdbX8MLBCwezlnhkHK0g==",
+ "requires": {
+ "@types/hoist-non-react-statics": "^3.0.1",
+ "hoist-non-react-statics": "^3.0.0",
+ "universal-cookie": "^4.0.0"
+ }
+ },
"react-dev-utils": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz",
@@ -34872,6 +34992,11 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
},
+ "react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -35276,6 +35401,12 @@
"symbol-observable": "^1.2.0"
}
},
+ "redux-persist": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/redux-persist/-/redux-persist-6.0.0.tgz",
+ "integrity": "sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==",
+ "requires": {}
+ },
"redux-thunk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
@@ -37681,6 +37812,15 @@
"crypto-random-string": "^1.0.0"
}
},
+ "universal-cookie": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz",
+ "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==",
+ "requires": {
+ "@types/cookie": "^0.3.3",
+ "cookie": "^0.4.0"
+ }
+ },
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
diff --git a/web/package.json b/web/package.json
index d5608955..e6c794f8 100644
--- a/web/package.json
+++ b/web/package.json
@@ -8,8 +8,10 @@
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^12.8.3",
"bootstrap": "^4.6.0",
+ "formik": "^2.2.6",
"react": "^17.0.2",
"react-bootstrap": "^1.5.2",
+ "react-cookie": "^4.0.3",
"react-dom": "^17.0.2",
"react-redux": "^7.2.3",
"react-router-dom": "^5.2.0",
@@ -17,6 +19,7 @@
"react-toast": "^1.0.1",
"react-toast-notifications": "^2.4.3",
"reactstrap": "^8.9.0",
+ "redux-persist": "^6.0.0",
"web-vitals": "^1.1.1"
},
"scripts": {
diff --git a/web/src/App.js b/web/src/App.js
index 26d9422f..30b0c7a2 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -2,14 +2,12 @@ import './App.css';
import Home from './Components/Pages/Home';
import About from './Components/Pages/About';
import Login from './Components/Pages/Login';
+import Settings from './Components/Pages/Settings';
import Register from './Components/Pages/Register';
import Navigation from './Components/Navigation';
-import { Route, Switch, HashRouter } from 'react-router-dom';
+import { Route, Switch } from 'react-router-dom';
import { connect } from "react-redux";
-
-import { ToastProvider } from 'react-toast-notifications';
-
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
function mapStateToProps(state) {
@@ -28,17 +26,16 @@ function mapDispatchToProps(dispatch) {
const App = () => {
let exact = true
return (
-
Registration is temporarily disabled. Please try again soon!
+ : ++ All the settings +
+