I am using the npm recaptcha verify plugin:
https://www.npmjs.com/package/recaptcha-verify
In my react app I am using
https://www.npmjs.com/package/react-google-invisible-recaptcha
At the top of my node app code:
var Recaptcha = require('recaptcha-verify');
var recaptcha = new Recaptcha({
secret: 'secret_key',
verbose: true
});
And then the route that works fine to send the email without recaptcha...
router.post('/mailer/recaptcha', function(req, res) {
var userResponse = req.query['g-recaptcha-response'];
console.log("user response: ", userResponse)
recaptcha.checkResponse(userResponse, function(error, response){
if(error){
// an internal error?
res.status(400).render('400', {
message: error.toString()
});
return;
}
if(response.success){
res.status(200).send('the user is a HUMAN :)');
// save session.. create user.. save form data.. render page, return json.. etc.
}else{
res.status(200).send('the user is a ROBOT :(');
// show warning, render page, return a json, etc.
}
});
In the form, using the react plugin, I am trying to follow the documentation as well, and it currently looks like this.
<Recaptcha
ref={ ref => this.recaptcha = ref }
sitekey="site_key"
onResolved={ this.testRecaptcha } />
The onResolved function attempts to validate the Recaptcha. this.testRecaptcha is a function that dispatches to our node route as seen above. In that route, where I console.log the userResponse,, I am getting undefined. That appears to be the main issue here, I think. The req also logs out all of the items in my form as part of the req.body, but nothing indicates that the recaptcha field is actually there.
testRecaptcha(e) {
let myObject = Object.assign({}, this.state.form, { sentFrom: 'contact', sendTo: this.state.sendTo });
this.props.dispatch(actions.sendTestToMailer(myObject));
}
When I inspect the code that is output from the recaptcha component it looks like this:
<div style="display: none;"><div class="grecaptcha-badge" style="width: 256px; height: 60px; transition: right 0.3s ease; position: fixed; bottom: 14px; right: -186px; box-shadow: gray 0px 0px 5px;"><div class="grecaptcha-logo"><iframe src="https://www.google.com/recaptcha/api2/anchor?k=sitekey&co=aHR0cDovL2xvY2FsaG9zdDo4MDgx&hl=en&v=v1514934548259&size=invisible&cb=oh5n23icp55m" width="256" height="60" role="presentation" frameborder="0" scrolling="no" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox"></iframe></div><div class="grecaptcha-error"></div><textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response" style="width: 250px; height: 40px; border: 1px solid #c1c1c1; margin: 10px 25px; padding: 0px; resize: none; display: none; "></textarea></div></div>
(where sitekey is the actual key -- not the text 'sitekey)
but, i receive the following error from the node.js app
{ success: false, 'error-codes': [ 'invalid-input-response' ] }
It seems I am not pushing the recaptcha data into this.state.form, but I am not sure what object needs to be pushed into that or if that is even the issue.
Does anyone have any insight on this? Is there an easier way to verify the invisible recaptcha? There is little to no documentation or working examples with every step to take here with node and react. Hopefully someone can help me and anyone else in a similar situtation?
------- EDIT -------------------------------------------------------
Based on feedback from trixn, made these changes and its almost working...
testRecaptcha(e) {
let recaptchaResponse = this.recaptcha.getResponse();
let myObject = Object.assign({}, this.state.form, { sentFrom: 'contact', sendTo: this.state.sendTo, recaptchaResponse:recaptchaResponse });
this.props.dispatch(actions.sendTestToMailer(myObject));
}
AND...
in the node backend:
var userResponse = req.body.recaptchaResponse;
recaptcha.checkResponse(userResponse, function(error, response){ etc..});
but... I am now getting this error.
Error parsing the response to an object. AND 'No default engine was specified and no extension was provided.'
You need to get the response token of your solved reCaptcha by accessing this.recaptcha.getResponse() in your onResolved callback then add that to your POST data and validate that in your node backend.
Related
I decided to dip my toes in Vue and have had an idea for a website for a while which I'd like to use amCharts5 for.
I had some issues initially as all the info I could find was related to Vue2, but I think I've somewhat wrapped my head around Vue3 and its composition API.
The MapChart is created, however there is always a div slapped on top of it which prevent any interaction. If I delete this element via DevTools, the MapChart becomes interactive.
I've tried debugging this and commenting sections of the code out, regardless this div is always created. And I simply can't figure out if it's injected by Vue or if amCharts 5 is the culprit.
The highlighted element is the one I must delete for it to become interactive.
Here's how the component is setup;
<template>
<div class="testClass" ref="chartdiv">
</div>
</template>
<script setup lang="ts">
import * as am5 from "#amcharts/amcharts5";
import * as am5map from "#amcharts/amcharts5/map";
import am5geodata_worldLow from "#amcharts/amcharts5-geodata/worldLow";
import am5themes_Animated from '#amcharts/amcharts5/themes/Animated';
import { ref, onMounted, onUnmounted } from "vue";
const chartdiv = ref<HTMLElement | null>()
var root!: am5.Root;
onMounted(() => {
if (chartdiv.value) {
// Create the Root
var root = am5.Root.new(chartdiv.value);
// Setup the MapChart
var chart = root.container.children.push(
am5map.MapChart.new(root, {
panX: "rotateX",
panY: "rotateY",
projection: am5map.geoOrthographic(),
centerMapOnZoomOut: false
})
);
// Setup Animations
root.setThemes([
am5themes_Animated.new(root)
]);
// Create MapPolygons
var polygonSeries = chart.series.push(
am5map.MapPolygonSeries.new(root, {
geoJSON: am5geodata_worldLow
})
);
// Setup MapPolygon Styling
polygonSeries.mapPolygons.template.setAll({
tooltipText: "{name}",
fill: am5.color("#909090")
});
// Setup MapPolygon Hover Styling
polygonSeries.mapPolygons.template.states.create("hover", {
fill: am5.color("#FF0000"),
stroke: am5.color("#00FF00"),
strokeWidth: 2
});
polygonSeries.mapPolygons.template.events.on("click", function(event) {
//console.log("Clicked: {0}", event.target);
});
// Setup Background
var backgroundSeries = chart.series.unshift(
am5map.MapPolygonSeries.new(root, {})
);
backgroundSeries.mapPolygons.template.setAll({
fill: am5.color(0x2c84d0),
stroke: am5.color(0x2c84d0)
});
backgroundSeries.data.push({
geometry: am5map.getGeoRectangle(90, 180, -90, -180)
});
}
});
onUnmounted(() => {
if (root) {
root.dispose();
}
});
</script>
<style scoped>
.testClass {
width: 50vw;
height: 50vh;
}
</style>
When you create a Vite-powered Vue project, it automatically creates a bunch of CSS files for you. One of those is base.css.
Inside this file, you'll find these lines which causes all the headache;
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
position: relative;
font-weight: normal;
}
Removing those lines will fix the issue.
I'm working on a Vue.js web app that needs to support video streaming. The backend is a Node.js app. It's pulling the videos from an S3 bucket and sending an unbuffered stream to the client. Here's the frontend code:
<template>
<div class="page-container">
<div v-if="currentVideo" class="pageContent">
<section-head>{{ currentVideo.name }}</section-head>
<p>{{ currentVideo.description }}</p>
<video
v-if="videoUrl"
:poster="currentVideo.thumbnail"
playsinline
controls
controlslist="nodownload"
class="stream"
type="video/mp4"
:key="videoUrl"
:src="videoUrl"
/>
<section-head>See More</section-head>
<gallery />
</div>
<h1 v-else class="sorry">
If you're seeing this message, you may have accidently gone to the wrong page.
Please go to the <router-link to="/">Home</router-link> page.
</h1>
</div>
</template>
<script>
import sectionHead from '../components/atoms/Header/SectionHead.vue';
import config from '../../config.js';
import gallery from '../components/molecules/Gallery/Gallery.vue';
export default {
name: 'Stream',
components: { sectionHead, gallery },
computed: {
currentVideo() {
return this.$store.state.currentVideo;
},
videoUrl() {
return 'https://' + config.currentEnvAPI() + '/stream/' + this.currentVideo.video;
},
},
};
</script>
<style lang="scss" scoped>
#import '../styles/_variables.scss';
.page-container {
margin: 0 auto;
p {
text-align: center;
font-size: 25px;
margin: 0 0 6px;
}
}
.stream {
display: block;
margin: 0 auto;
width: 750px;
height: auto;
outline: none;
#include tablet {
width: 650px;
}
#include phone {
width: 100%;
}
}
.sorry {
text-align: center;
padding: 120px;
}
</style>
And I'm setting and getting the video object from VueX here:
import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions.js';
import mutations from './mutations.js';
Vue.use(Vuex);
const state = {
videoList: [],
videoObjects: [],
loadingData: false,
currentVideo: null,
currentGallery: [],
};
export default new Vuex.Store({
state,
actions,
mutations,
});
This is the route that I'm calling on the backend:
app.get('/stream/:video', async (req, res) => {
let videoParams = {
Bucket: BUCKET_NAME,
Key: req.params.video,
};
S3.getObject(videoParams)
.on('httpHeaders', function (statusCode, headers) {
res.set('Content-Length', headers['content-length']);
res.set('Content-Type', headers['content-type']);
res.set('Accept-Ranges', headers['accept-ranges']);
this.response.httpResponse.createUnbufferedStream()
.pipe(res);
})
.send();
});
As far as I can tell, this is a good implementation because it works fine on desktop, both locally and deployed. I only have issues on mobile browsers. I've tried both Chrome and Safari on two different iPhones (no access to an Android device). This is all I see for all of my videos:
I also took the time to set up an SSL certificate for all of my endpoints, so I know the videos are streaming over https. I was thinking that the size of the videos (between 250 - 550 MB) may be the issue, but I also noticed that even though the element is disabled, the connection still transfers the whole thing.
I would think if it was a server side issue that it wouldn't send the whole file, but it does. So wouldn't the issue be client side? I can't figure out why it's not working though. The files are mp4 and I'm sure that they should work because I've tried other links to test with mp4 videos and they've worked. I've changed up the element attributes a lot too. I've tried both with and without playsinline, autoplay, and muted. I've tried having the source element as a child of the video element and that still didn't work. I'm also not getting any console errors, so I can't figure out what the actual problem is and I'm not sure how else I can troubleshoot this.
the h.264 profile of your example file in the comments is "high" but ios safari only supports "base". if you open the file directly in safari, it won't play either.
see https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html#//apple_ref/doc/uid/TP40009523-CH5-SW9
Im testing using react-testing-library and jest-styled-components.
I have a wrapper component that renders the styles of its child button dependant on a selected prop passed to it.
This is the code:
const selectedStyles = css`
background-image: url(../image);
background-position: center;
background-repeat: no-repeat;
border-color: ${color.grey6};
height: 38px;
width: 58px;
& span {
display: none;
}
`;
const ButtonWrapper = styled.div`
& button {
font-size: 15px;
line-height: 20px;
padding: 8px 12px;
${props =>
props.selected
? css`
${selectedStyles}
`
: ""}
&:hover,
:focus {
${props =>
props.selected
? css`
${selectedStyles}
`
: ""}
}
}
`;
and the test
test("it renders the correct styles when selected ", () => {
const { container } = render(<CheckButton selected>Add</CheckButton>);
const button = container.querySelector("button");
expect(button).toHaveStyleRule("background-position", "center");
});
but its failing with "Property 'background-position' not found in style rules" which is true for the original button, however when its parent is passed the selected prop this style applies.
I am also doing snapshot testing with the component however not testing the props getting passed brings the test coverage down.
Can anyone help?
In general as far as nested styles testing is concerned, I would recommend testing directly the nested element.
I personally haven't figured out a way to test nested styles using the .toHaveStyle(``); (not even a simple
a {
text-decoration: none;
}
)
so I ended up querying for the exact component I wanted to test, eg:
expect(screen.getByText(/text-within-the-child-component/i)).toHaveStyle(`
text-decoration: none;
`);
In your specific case I believe the way to go is to render your component in your test directly with the props that trigger the styles you want for each case (selected in your code example).
For those who are facing the same problem toHaveStyleRule accept a third "options" parameter after property and value where you can path a modifier:
test("it renders the correct styles when selected ", () => {
render(<CheckButton selected>Add</CheckButton>);
const button = container.querySelector("button");
expect(screen.getByText("Add").parentElement).toHaveStyleRule("background-position", "center", { modifier: 'button' });
});
Here I state on the fact that "Add" is the button text and its parent is the component ButtonWrapper.
By the way, you should avoid as much as possible using querySelector (here I'm using react testing library).
https://github.com/styled-components/jest-styled-components
So task is simple, but not for me - green Gnome Extensions Development noob. Of course I googled this, but didn't find something that can be helpful here.
extension.js:
https://pastebin.com/TqDVp8Yz - because 'your post mostly code'.
stylesheet.css:
.poppy-button {
background-size: 20px;
width: 20px;
height: 20px;
background-image: url("Resources/poppy.svg");
}
.poppy-button:active,
.poppy-button:focus,
.poppy-button:checked,
.poppy-button:hover {
background-image: url("Resources/poppy-active.svg");
}
I would avoid the CSS and connect to the "enter-event" and "leave-event" signals, since all StWidget elements are also ClutterActors.
myIcon = new St.Icon({ icon_name: "normal-icon-name"; });
myIcon.connect("enter-event", (widget) => {
widget.icon_name = "hover-icon-name";
});
myIcon.connect("leave-event", (widget) => {
widget.icon_name = "normal-icon-name";
});
On the other hand, your CSS might work if you set "track-hover" to true on the StIcon.
Pro-Amateur-Tip: add the "gjs" tag to you questions to pull in more help for Gnome Shell extensions.
So currently I am working with VueJS 2 and I am very new with it. Now I was getting some help with some other people, but I am still stuck.
Here is what I want to achieve (example - closely linked to what I want):
I have a NodeJS application that listens on WebSockets. The application listens for connections via WebSocket and will take JSON data, with a command and then a data object with any content needed for that command.
The command for example could be login, and the data be username and password. The login function on the NodeJS application will then take this data, do what it needs and then return it back over the socket, whether it was successful or not, and maybe include an ID and some user information for Vuex to pickup and place in it's state, for the front-end of the application to pick up/use.
Currently I am using this boiler plate: https://github.com/SimulatedGREG/electron-vue
Which has served me very well as a learning curve, due to me wanting to use Vue and Vuex to manage my application and then use WebSockets for managing data to and from the data server.
So if you look at the link I sent in app/src/renderer/ (this is where the main code is for vue and vuex).
A friend of mine added the following code for me as an example and I am stuck trying to get it into vuex as actions and mutations. He made it all in one vue component, so I am struggling on how it works with vuex. As I want to be able to access the (example) loginUser action from anywhere in the application (uses routes for multiple pages/views).
So in the MyApp/app/src/renderer/components/LandingPageView.vue
<template>
<div>
<img src="./LandingPageView/assets/logo.png" alt="electron-vue">
<h1>Welcome.</h1>
<current-page></current-page>
<websocket-output></websocket-output>
<versions></versions>
<links></links>
</div>
</template>
<script>
import CurrentPage from './LandingPageView/CurrentPage'
import Links from './LandingPageView/Links'
import Versions from './LandingPageView/Versions'
import WebsocketOutput from './LandingPageView/WebsocketOutput'
export default {
components: {
CurrentPage,
Links,
Versions,
WebsocketOutput
},
name: 'landing-page'
}
</script>
<style scoped>
img {
margin-top: -25px;
width: 450px;
}
</style>
That is the updated file for that, and then below is the code for the MyApp/app/src/renderer/components/LandingPageView/WebsocketOutput.vue
<template>
<div>
<h2>Socket output:</h2>
<p v-text="socket_out"></p>
</div>
</template>
<script>
var ws = require("nodejs-websocket")
export default {
data () {
return {
socket_out: "connecting to the websocket server..."
}
},
mounted () {
const parent = this
var connection = ws.connect("ws://dannysmc.com:9999", {}, function (conn) {})
connection.on("text", function (text) {
console.log('Text received: ' + text)
parent.socket_out = text
})
connection.on("connect", function () {
connection.send('yo')
})
},
created () {
// Set $route values that are not preset during unit testing
if (process.env.NODE_ENV === 'testing') {
this.$route = {
name: 'websocket-output',
path: '/websocket-output'
}
}
}
}
</script>
<style scoped>
code {
background-color: rgba(46, 56, 76, .5);
border-radius: 3px;
color: #fff;
font-weight: bold;
padding: 3px 6px;
margin: 0 3px;
vertical-align: bottom;
}
p {
line-height: 24px;
color: red;
}
</style>
Everything else is just the boiler plate that you see, so if anyone is willing to help me and give me some tips of what to read that explains this or anything else? as I can't find much information on it unfortunately.
I have an electron application that uses Vue and a websocket for information and here is how I set mine up.
I have a store defined that also actually creates and sets up the websocket.
Store.js
const socket = require("socket-library") // Take your pick of socket libs
const mySocket = new socket(...)
mySocket.on("message", message => store.handleMessage(message))
...other handlers...
const store = {
handleMessage(message){
// do things with the message
}
}
export default store
Renderer.js
import store from "./store"
new Vue({
data:{
store
}
})
This exposes my store at the root level of my Vue and allows me to pass data to components, or what have you. The store manages all the incoming information from the websocket.
With you wanting to use Vuex, you could do essentially the same thing, where Vuex would be your store and when messages come in over the socket, you just pass them to Vuex.
mySocket.on("message", msg => vuexStore.dispatch("onSocketMessage", msg))
and set up your Vue and components to work with Vuex as you typically would.