diff --git a/.github/workflows/logging.yml b/.github/workflows/logging.yml new file mode 100644 index 0000000..f70cfeb --- /dev/null +++ b/.github/workflows/logging.yml @@ -0,0 +1,133 @@ +name: Deploy Elasticsearch, Install Fluentd and Configure + +on: + push: + branches: + - main + paths: + - '.github/workflows/logging.yml' + + +jobs: + deploy_elasticsearch_install_and_configure_fluentd: + runs-on: ubuntu-latest + env: + CLUSTER_NAME: ${{ secrets.ELASTICSEARCH_CLUSTER_NAME }} + ELASTICSEARCH_HOST: ${{ secrets.ELASTICSEARCH_HOST }} + ELASTICSEARCH_PORT: ${{ secrets.ELASTICSEARCH_PORT }} + ELASTICSEARCH_USERNAME: ${{ secrets.ELASTICSEARCH_USERNAME }} + ELASTICSEARCH_PASSWORD: ${{ secrets.ELASTICSEARCH_PASSWORD }} + + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Check if Fluentd is installed + id: check_fluentd + run: | + if ! command -v td-agent &> /dev/null + then + echo "::set-output name=installed:: false" + else + echo "::set-output name=installed::true" + fi + + - name: Install Fluentd, copy config file, start service and open ports + if: steps.check_fluentd.outputs.installed == 'false' + uses: appleboy/ssh-action@v0.1.10 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + sudo apt-get update + sudo apt-get install -y gnupg2 curl + curl -sSL https://toolbelt.treasuredata.com/sh/install-ubuntu-focal-td-agent4.sh | sudo sh + cp fluentd.conf /etc/td-agent/fluentd.conf + sudo systemctl start td-agent + - name: Copy Config file to server and open ports + uses: appleboy/ssh-action@v0.1.10 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + sudo cp /etc/td-agent/fluentd.conf /etc/td-agent/fluentd.conf.bak + sudo cp fluentd.conf /etc/td-agent/fluentd.conf + sudo systemctl restart td-agent + sudo systemctl status td-agent + fluentd -c in_docker.conf + - name: Open specified ports on the server + uses: appleboy/ssh-action@v0.1.10 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + sudo ufw allow 9200 # Allow traffic on Elasticsearch port + sudo ufw allow 9300 # Allow traffic on Elasticsearch port(inter-node communication) + sudo ufw allow 5601 # Allow traffic on Kibana port + sudo ufw reload # Reload firewall to apply changes + - name: Create Docker volume for Elasticsearch data + run: docker volume create elasticsearch_data + + - name: Run Elasticsearch container with volume mount + uses: appleboy/ssh-action@v0.1.10 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + script: | + docker run -d --name elasticsearch \ + -p 9200:9200 -p 9300:9300 \ + -e "discovery.type=single-node" \ + -e "cluster.name=${{ env.CLUSTER_NAME }}" \ + -v elasticsearch_data:/var/lib/elasticsearch/data + -v :/var/lib/elasticsearch/logs \ + --restart=always \ + docker.elastic.co/elasticsearch/elasticsearch:8.12.2 + - name: Wait for Elasticsearch to start + run: docker exec elasticsearch sh -c 'until curl -sSf localhost:9200; do sleep 1; done' + + - name: Create and apply Index Lifesycle Management Policy(ILM) policy + run: | + curl -X PUT "localhost:9200/_ilm/policy/one_year_policy" -H 'Content-Type: application/json' -d' + { + "policy": { + "phases": { + "hot": { + "actions": { + "rollover": { + "max_age": "30d" + } + } + }, + "delete": { + "min_age": "365d", + "actions": { + "delete": {} + } + } + } + } + }' + curl -X PUT "localhost:9200/fluentd/_settings" -H 'Content-Type: application/json' -d' + { + "index": { + "lifecycle": { + "name": "one_year_policy" + } + } + }' + - name: Run Kibana Container + run: | + docker run -d --name kibana \ + -p 5601:5601 \ + -e "ELASTICSEARCH_USERNAME=${{ secrets.ELASTICSEARCH_USERNAME }}" \ + -e "ELASTICSEARCH_PASSWORD=${{ secrets.ELASTICSEARCH_PASSWORD }}" \ + -e "ELASTICSEARCH_HOSTS=http://elasticsearch:9200" \ + --restart=always \ + docker.elastic.co/kibana/kibana:8.12.2 + - name: Wait for Kibana to start + run: docker exec kibana sh -c 'until curl -sSf localhost:5601; do sleep 1; done' diff --git a/fluentd.conf b/fluentd.conf new file mode 100644 index 0000000..d9be7f2 --- /dev/null +++ b/fluentd.conf @@ -0,0 +1,27 @@ +# Input Plugin: Docker Logs + + @type docker + tag docker.* + @log_level debug + @log_opts ["env=production"] + + +# Filter Plugin: (Optional) Parse and Enrich Logs + + @type parser + key_name log + + @type json + + + +# Output Plugin: Send Logs to Elasticsearch + + @type elasticsearch + host "#{ENV['ELASTICSEARCH_HOST']}" + port "#{ENV['ELASTICSEARCH_PORT']}" + index_name fluentd + type_name _doc + include_tag_key true + tag_key @log_name + \ No newline at end of file diff --git a/helpers/awardBadge.js b/helpers/awardBadge.js index 6058912..fd6e8f3 100644 --- a/helpers/awardBadge.js +++ b/helpers/awardBadge.js @@ -1,3 +1,4 @@ +const logger = require("./logger"); const badgeLink = "https://raw.githubusercontent.com/badging/badging/main/src/assets/images/badges/bronze-badge.svg"; @@ -29,6 +30,8 @@ const awardBadge = async (octokit, owner, repoName) => { }); console.log("Badge added to README successfully."); + // Log success message + logger.info("Badge added to README successfully.", { owner, repoName }); } catch (error) { console.error("Error awarding badge:", error); } diff --git a/logger.js b/logger.js new file mode 100644 index 0000000..72c1d35 --- /dev/null +++ b/logger.js @@ -0,0 +1,19 @@ +const winston = require("winston"); + +// Create a Winston logger +const logger = winston.createLogger({ + format: winston.format.combine( + winston.format.timestamp(), // Add timestamp to log messages + winston.format.json() // Use JSON format for log messages + ), + transports: [ + new winston.transports.Http({ + host: "localhost", + port: 24224, // Fluentd port + path: "/debug.fluentd", // Fluentd input path + ssl: false, // Use SSL if required + }), + ], +}); + +module.exports = logger; \ No newline at end of file diff --git a/loggerauth.js b/loggerauth.js new file mode 100644 index 0000000..779e7fb --- /dev/null +++ b/loggerauth.js @@ -0,0 +1,60 @@ +const express = require("express"); +const session = require("express-session"); +const logger = require("./logger"); +const router = express.Router(); + +router.use(express.urlencoded({ extended: true })); +router.use( + session({ + secret: "my-secret", + resave: false, + saveUninitialized: true, + }) +); + +router.get("/logs", (req, res) => { + logger.info("Admin user accessed login page"); + res.send(` +
+ +

+ + input type="password" id="password" name="password">

+ +
+ `); +}); + +//Authentication +router.post("/logs/login", (req, res) => { + const { username, password } = req.body; + const validUsername = process.env.ELASTICSEARCH_USERNAME; // Replace with your environment variable for username + const validPassword = process.env.ELASTICSEARCH_PASSWORD; // Replace with your environment variable for password + + if (username === validUsername && password === validPassword) { + req.session.user = { username: validUsername }; + logger.info("User logged in successfully"); + res.redirect("dashboard"); + } else { + logger.error("Invalid username or password"); + res.send("Invalid username or password"); + } +}); + +router.get("/logs/dashboard", (req, res) => { + if (req.session && req.session.user) { + logger.info("User accessed dashboard"); + res.redirect("/kibana-dashboard"); + } else { + logger.warn("Unauthorized access to dashboard"); + res.redirect("/logs"); + } +}); + +// Route to redirect to Kibana dashboard +router.get("/kibana-dashboard", (req, res) => { + // Redirect to Kibana dashboard URL + res.redirect("http://localhost:5601"); +}); + +module.exports = router; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index f7dcc8e..0f4919c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,12 +17,14 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "express-http-proxy": "^2.0.0", + "express-session": "^1.18.0", "mongoose": "^7.4.1", "mysql2": "^3.6.0", "nodemailer": "^6.9.3", "nodemon": "^2.0.22", "octokit": "^2.1.0", - "sequelize": "^6.32.1" + "sequelize": "^6.32.1", + "winston": "^3.12.0" }, "devDependencies": { "eslint-config-prettier": "^8.8.0", @@ -48,6 +50,24 @@ "node": ">=6.9.0" } }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -888,6 +908,11 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@types/validator": { "version": "13.11.1", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", @@ -1144,6 +1169,11 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1436,6 +1466,15 @@ "node": ">= 12" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1452,12 +1491,43 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1754,6 +1824,11 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -2337,6 +2412,50 @@ "node": ">=6.0.0" } }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/express/node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -2437,6 +2556,11 @@ "reusify": "^1.0.4" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -2551,6 +2675,11 @@ "dev": true, "peer": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -3097,6 +3226,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -3561,6 +3695,11 @@ "node": ">=12.0.0" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -3856,6 +3995,22 @@ "node": ">=8" } }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -4480,6 +4635,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4488,6 +4651,14 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -4767,6 +4938,14 @@ ], "peer": true }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -4789,6 +4968,19 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4999,6 +5191,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5244,6 +5444,14 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/simple-update-notifier": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", @@ -5330,6 +5538,14 @@ "node": ">= 0.6" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -5350,6 +5566,14 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -5516,6 +5740,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5580,6 +5809,14 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -5650,6 +5887,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -5713,6 +5961,11 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -5825,6 +6078,51 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/winston": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.12.0.tgz", + "integrity": "sha512-OwbxKaOlESDi01mC9rkM0dQqQt2I8DAUMRLZ/HpbwvDXm85IryEHgoogy5fziQy38PntgZsLlhAYHz//UPHZ5w==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.7.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", diff --git a/package.json b/package.json index 2b410b2..6186178 100644 --- a/package.json +++ b/package.json @@ -35,12 +35,14 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "express-http-proxy": "^2.0.0", + "express-session": "^1.18.0", "mongoose": "^7.4.1", "mysql2": "^3.6.0", "nodemailer": "^6.9.3", "nodemon": "^2.0.22", "octokit": "^2.1.0", - "sequelize": "^6.32.1" + "sequelize": "^6.32.1", + "winston": "^3.12.0" }, "devDependencies": { "eslint-config-prettier": "^8.8.0", diff --git a/routes/index.js b/routes/index.js index f6770e5..ead8eeb 100644 --- a/routes/index.js +++ b/routes/index.js @@ -3,6 +3,7 @@ const Repo = require("../database/models/repo.model.js"); const eventBadging = require("../event_badging/index.js"); const github_helpers = require("../providers/github/APICalls.js"); const gitlab_helpers = require("../providers/gitlab/APICalls.js"); +const logger = require("./logger"); const { githubAuth, githubAuthCallback, @@ -16,18 +17,34 @@ const { * @param {*} req - object containing the client req details. * @param {*} res - object used to send a redirect response. */ + const login = (req, res) => { const provider = req.query.provider; if (provider === "github") { - githubAuth(req, res); + githubAuth(req, res).then(userData => { + // Log successful login + logger.info(`User ${userData.login} logged in via Github`); + }).catch(error => { + console.error("Authentication error:", error); + res.status(500).send("Authentication failed"); + }); } else if (provider === "gitlab") { - gitlabAuth(req, res); + gitlabAuth(req, res).then(userData => { + // Log successful login + logger.info(`User ${userData.username} logged in via Gitlab`); + }).catch(error => { + console.error("Authentication error:", error); + res.status(500).send("Authentication failed"); + }); } else { + // Log unknown provider + logger.warn(`Unknown provider: ${provider}`); res.status(400).send(`Unknown provider: ${provider}`); } }; + const reposToBadge = async (req, res) => { const selectedRepos = (await req.body.repos) || []; const userId = req.body.userId; @@ -100,6 +117,9 @@ const reposToBadge = async (req, res) => { const badgedRepos = async (req, res) => { try { + // Log the start of the function execution + logger.info("Fetching badged repositories"); + // Use Sequelize to find all repos, excluding the DEICommitSHA field const repos = await Repo.findAll({ attributes: { exclude: ["DEICommitSHA"] }, @@ -117,8 +137,15 @@ const badgedRepos = async (req, res) => { userId: repo.userId, })); + // Log the number of nadged repositories retrieved + logger.info( + "Number of badged repositories retrieved: ${formattedRepos.length}" + ); + res.json(formattedRepos); } catch (error) { + // Log error if an exception occurs during repository retrieval + logger.error("Error retrieving badged repositories", { error }); res.status(500).json({ message: "Error retrieving repos", error }); } };