mirror of
https://github.com/anatolykopyl/vk-bingo.git
synced 2026-03-26 04:44:26 +00:00
🛂 Добавил авторизацию
This commit is contained in:
@@ -6,9 +6,14 @@ const MongoStore = require('connect-mongo')
|
|||||||
const cors = require('cors')
|
const cors = require('cors')
|
||||||
require('dotenv').config()
|
require('dotenv').config()
|
||||||
|
|
||||||
const {verifyCaptcha} = require('./verify-captcha')
|
app.use(cors({
|
||||||
|
origin: [
|
||||||
app.use(cors())
|
'http://localhost:8080',
|
||||||
|
'https://localhost:8080'
|
||||||
|
],
|
||||||
|
credentials: true,
|
||||||
|
exposedHeaders: ['set-cookie']
|
||||||
|
}))
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
app.use(express.urlencoded({ extended: true }))
|
app.use(express.urlencoded({ extended: true }))
|
||||||
|
|
||||||
@@ -23,13 +28,18 @@ app.use(session({
|
|||||||
client,
|
client,
|
||||||
dbName: process.env.DB_NAME
|
dbName: process.env.DB_NAME
|
||||||
}),
|
}),
|
||||||
cookie: { maxAge: 1000 * 60 * 60 * 24 }
|
cookie: {
|
||||||
|
secure: false,
|
||||||
|
maxAge: 1000 * 60 * 60 * 24
|
||||||
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
client.connect()
|
client.connect()
|
||||||
|
|
||||||
app.post('/auth', async (req, res) => {
|
app.post('/auth', async (req, res) => {
|
||||||
verifyCaptcha(req, res, async () => {
|
if (req.session.loggedIn) {
|
||||||
|
res.status(200).send("Logged in")
|
||||||
|
} else {
|
||||||
try {
|
try {
|
||||||
const pass = req.body.pass
|
const pass = req.body.pass
|
||||||
if (pass.toLowerCase() === process.env.PASSWORD) {
|
if (pass.toLowerCase() === process.env.PASSWORD) {
|
||||||
@@ -42,7 +52,7 @@ app.post('/auth', async (req, res) => {
|
|||||||
console.log("Error: " + e)
|
console.log("Error: " + e)
|
||||||
res.status(500).send()
|
res.status(500).send()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/card', async (req, res) => {
|
app.get('/card', async (req, res) => {
|
||||||
|
|||||||
22
backend/package-lock.json
generated
22
backend/package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"connect-mongo": "^4.4.1",
|
"connect-mongo": "^4.4.1",
|
||||||
|
"cookie-parser": "^1.4.5",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
@@ -537,6 +538,18 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cookie-parser": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "0.4.0",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cookie-signature": {
|
"node_modules/cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
@@ -2562,6 +2575,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||||
},
|
},
|
||||||
|
"cookie-parser": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==",
|
||||||
|
"requires": {
|
||||||
|
"cookie": "0.4.0",
|
||||||
|
"cookie-signature": "1.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"connect-mongo": "^4.4.1",
|
"connect-mongo": "^4.4.1",
|
||||||
|
"cookie-parser": "^1.4.5",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
const axios = require('axios')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
verifyCaptcha: function (req, res, cb) {
|
|
||||||
if (!req.body['g-recaptcha-response']) {
|
|
||||||
return res.status(400).send("No captcha")
|
|
||||||
}
|
|
||||||
|
|
||||||
const URL = "https://www.google.com/recaptcha/api/siteverify?secret=" + process.env.SECRET_KEY + "&response=" + req.body['g-recaptcha-response'] + "&remoteip=" + req.socket.remoteAddress
|
|
||||||
|
|
||||||
axios.get(URL).then(function (response) {
|
|
||||||
if (response.data.success !== undefined && !response.data.success) {
|
|
||||||
return res.status(429).send("Invalid captcha")
|
|
||||||
}
|
|
||||||
|
|
||||||
cb()
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
43
frontend/package-lock.json
generated
43
frontend/package-lock.json
generated
@@ -18,6 +18,7 @@
|
|||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"@vue/compiler-sfc": "^3.0.0",
|
"@vue/compiler-sfc": "^3.0.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
|
"dotenv-webpack": "^7.0.2",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^7.0.0"
|
"eslint-plugin-vue": "^7.0.0"
|
||||||
}
|
}
|
||||||
@@ -5265,12 +5266,36 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv-defaults": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-ugFCyBF7ILuwpmznduHPQZBMucHHJ8T4OBManTEVjemxCm2+nqifSuW2lD2SNKdiKSH1E324kZSdJ8M04b4I/A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^8.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dotenv-expand": {
|
"node_modules/dotenv-expand": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz",
|
||||||
"integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
|
"integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/dotenv-webpack": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-RY+/5uM/XY4bGtih9f9ic8hlrUDxVcZZBPWlnX/aHhaKxcVVX9SH/5VH7CSmvVo9GL6PKvQOA0X1bc552rnatQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv-defaults": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"webpack": "^4 || ^5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/duplexer": {
|
"node_modules/duplexer": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz?cache=0&sync_timestamp=1597221020457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fduplexer%2Fdownload%2Fduplexer-0.1.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz?cache=0&sync_timestamp=1597221020457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fduplexer%2Fdownload%2Fduplexer-0.1.2.tgz",
|
||||||
@@ -19288,12 +19313,30 @@
|
|||||||
"integrity": "sha1-l+YZJZradQ7qPk6j4mvO6lQksWo=",
|
"integrity": "sha1-l+YZJZradQ7qPk6j4mvO6lQksWo=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dotenv-defaults": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-ugFCyBF7ILuwpmznduHPQZBMucHHJ8T4OBManTEVjemxCm2+nqifSuW2lD2SNKdiKSH1E324kZSdJ8M04b4I/A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"dotenv": "^8.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dotenv-expand": {
|
"dotenv-expand": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/dotenv-expand/download/dotenv-expand-5.1.0.tgz",
|
||||||
"integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
|
"integrity": "sha1-P7rwIL/XlIhAcuomsel5HUWmKfA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dotenv-webpack": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-RY+/5uM/XY4bGtih9f9ic8hlrUDxVcZZBPWlnX/aHhaKxcVVX9SH/5VH7CSmvVo9GL6PKvQOA0X1bc552rnatQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"dotenv-defaults": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"duplexer": {
|
"duplexer": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz?cache=0&sync_timestamp=1597221020457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fduplexer%2Fdownload%2Fduplexer-0.1.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/duplexer/download/duplexer-0.1.2.tgz?cache=0&sync_timestamp=1597221020457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fduplexer%2Fdownload%2Fduplexer-0.1.2.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"@vue/compiler-sfc": "^3.0.0",
|
"@vue/compiler-sfc": "^3.0.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
|
"dotenv-webpack": "^7.0.2",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^7.0.0"
|
"eslint-plugin-vue": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,15 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<h1>🎰 Flex Bingo 🎰</h1>
|
<h1>🎰 Flex Bingo 🎰</h1>
|
||||||
<Game id="game" />
|
<Login id="login" @loggedIn="login" v-show="!loggedIn" />
|
||||||
|
<Game id="game" v-if="loggedIn" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Login from './components/Login.vue'
|
||||||
import Game from './components/Game.vue'
|
import Game from './components/Game.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
components: {
|
components: {
|
||||||
|
Login,
|
||||||
Game
|
Game
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loggedIn: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
login: function(success) {
|
||||||
|
this.loggedIn = success
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -30,7 +43,17 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#game {
|
#game {
|
||||||
margin-left: 25%;
|
margin: auto;
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.correct {
|
||||||
|
background-color: rgb(124, 230, 124) !important;
|
||||||
|
}
|
||||||
|
.highlight_correct {
|
||||||
|
border: 1px solid rgb(124, 230, 124);
|
||||||
|
}
|
||||||
|
.wrong {
|
||||||
|
background-color: rgb(255, 71, 71) !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card" v-if="card!==null">
|
<div class="card" v-if="card !== null">
|
||||||
<img class="meme" v-bind:src="card.image">
|
<img class="meme" v-bind:src="card.image">
|
||||||
<h2>Кто скинул этот мем?</h2>
|
<h2>Кто скинул этот мем?</h2>
|
||||||
<div class="answers">
|
<div class="answers">
|
||||||
@@ -82,13 +82,15 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.correct {
|
@keyframes correct-selected {
|
||||||
background-color: rgb(124, 230, 124);
|
0% {
|
||||||
}
|
transform: scale(0);
|
||||||
.highlight_correct {
|
}
|
||||||
border: 1px solid rgb(124, 230, 124);
|
50% {
|
||||||
}
|
transform: scale(1.5);
|
||||||
.wrong {
|
}
|
||||||
background-color: rgb(255, 71, 71);
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
74
frontend/src/components/Login.vue
Normal file
74
frontend/src/components/Login.vue
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>Авторизация:</h1>
|
||||||
|
<p>{{ question }}</p>
|
||||||
|
<input v-model="answer"><br>
|
||||||
|
<button v-on:click="login" v-bind:class="{wrong: loggedIn === false}">Ввод</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
axios.defaults.withCredentials = true
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Login',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
question: null,
|
||||||
|
answer: null,
|
||||||
|
loggedIn: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
login: function() {
|
||||||
|
axios
|
||||||
|
.post('http://localhost:3000/auth', {
|
||||||
|
"pass": this.answer,
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
this.loggedIn = response.status == "200"
|
||||||
|
this.$emit('loggedIn', this.loggedIn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.question = process.env.VUE_APP_QUESTION
|
||||||
|
|
||||||
|
this.login()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
div {
|
||||||
|
background-color: #121212;
|
||||||
|
width: 400px;
|
||||||
|
margin: auto;
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 40px 10px 40px 10px;
|
||||||
|
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 8px 5px 8px;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
width: 20ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: white;
|
||||||
|
font-size: 1em;
|
||||||
|
box-sizing: content-box;
|
||||||
|
background-color: #5a5a5a;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
width: 20ch;
|
||||||
|
padding: 5px 8px 5px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user