Software
Getting a Post 403 Forbidden with Spring Boot (VueJS and Axios Frontend)
I've been having an issue with CORS and I have tried everything I could find on Stack Overflow and basically anything that I found on Google and have had no luck.
So I have user authentication on my backend and I have a login page on my frontend. I hooked up the login page with Axios so I could make a post request and tried to login but I kept getting errors like "Preflight request" so I fixed that then I started getting the "Post 403 Forbidden" error.
It appeared like this:
POST http://localhost:8080/api/v1/login/ 403 (Forbidden)Even trying to login using Postman doesn't work so something is clearly wrong. Will be posting class files below
On my backend, I have a class called WebSecurityConfig which deals with all the CORS stuff:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsService; @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedMethods("GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS"); } }; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); // TODO: lock down before deploying config.addAllowedHeader("*"); config.addExposedHeader(HttpHeaders.AUTHORIZATION); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Override protected void configure(HttpSecurity http) throws Exception { http.headers().frameOptions().disable(); http .cors() .and() .csrf().disable().authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/h2/**").permitAll() .antMatchers(HttpMethod.POST, "/api/v1/login").permitAll() .anyRequest().authenticated() .and() // We filter the api/login requests .addFilterBefore(new JWTLoginFilter("/api/v1/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class); // And filter other requests to check the presence of JWT in header //.addFilterBefore(new JWTAuthenticationFilter(), // UsernamePasswordAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // Create a default account auth.userDetailsService(userDetailsService); // auth.inMemoryAuthentication() // .withUser("admin") // .password("password") // .roles("ADMIN"); } }On our frontend which is written in VueJS and using Axios to make the call
<script> import { mapActions } from 'vuex'; import { required, username, minLength } from 'vuelidate/lib/validators'; export default { data() { return { form: { username: '', password: '' }, e1: true, response: '' } }, validations: { form: { username: { required }, password: { required } } }, methods: { ...mapActions({ setToken: 'setToken', setUser: 'setUser' }), login() { this.response = ''; let req = { "username": this.form.username, "password": this.form.password }; this.$http.post('/api/v1/login/', req) .then(response => { if (response.status === 200) { this.setToken(response.data.token); this.setUser(response.data.user); this.$router.push('/dashboard'); } else { this.response = response.data.error.message; } }, error => { console.log(error); this.response = 'Unable to connect to server.'; }); } } } </script>So when I debugged via Chrome's tools (Network), I noticed that the OPTIONS request goes through as shown below:
Here is a picture of the POST error:
Here is another class which handles the OPTIONS request (JWTLoginFilter as referenced in the WebSecurityConfig):
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter { public JWTLoginFilter(String url, AuthenticationManager authManager) { super(new AntPathRequestMatcher(url)); setAuthenticationManager(authManager); } @Override public Authentication attemptAuthentication( HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException { AccountCredentials creds = new ObjectMapper() .readValue(req.getInputStream(), AccountCredentials.class); if (CorsUtils.isPreFlightRequest(req)) { res.setStatus(HttpServletResponse.SC_OK); return null; } return getAuthenticationManager().authenticate( new UsernamePasswordAuthenticationToken( creds.getUsername(), creds.getPassword(), Collections.emptyList() ) ); } @Override protected void successfulAuthentication( HttpServletRequest req, HttpServletResponse res, FilterChain chain, Authentication auth) throws IOException, ServletException { TokenAuthenticationService .addAuthentication(res, auth.getName()); } }Axios not loading data to vue
I am trying to load cytoscape graph using vue and axios. Anyway cant configure cytoscape so I tried first with axios and vue only. There is still problem with scope, but I can't figure where? What should I change? How to properly set vuew and axios.
app = new Vue({ el: '#app', data:{ projekt: null, cy: null, nodes: [], edges :[], }, created(){ }, methods:{ to: function(){ var vm = this; axios.get('/json' + window.location.pathname) .then(function (response) { vm.projekt = response.data }); }, dodajElement: function(){ this.to(); console.log(this.projekt); } }Vuejs sending multiple get requests
I am making a Vuejs post request when component is mounted (using Vuex actually), and it all looks good. But when I inspect the console under network tab, I see that the get request is actually sent to the backend multiple times when the page loads. Is this normal? This is my request (using axios)
// component calling Store action methods: { ...mapActions({ fetchItems: 'items/fetchCart' }), }, mounted(){ this.fetchItems(); }Now in Axios, this is the action sent to the backend
const actions = { fetchItems({commit}){ return axios.get('/api/items').then((response) => { // commit a mutation to set the items in the state commit('SET_ITEMS', response.data) }).catch((error) => { console.log(error) }) }, }So this fetches the items just fine and populates the store, but I see from the network tab of my browser that this request is actually sent multiple times (5 times), which kind of affects some of my other logic in the backend.
I am using Laravel5.4 as the backend BTW.
Parent-child communication in VueJS
I have two Vue components. The parent-component:
Vue.component('parent-component',{ methods: { test: function(){ alert('Option Selected'); } }, template: ` <div><slot></slot></div> ` });And the animals component:
Vue.component('animals',{ data: function(){ return { selected: '' } }, template: ` <select @change="selectionChanged" v-model="selected"> <slot></slot> </select> `, methods: { selectionChanged: function(){ this.$emit('optionselected', this.selected); } } });And here is my HTML:
<div id="app"> <parent-component @optionselected="test()"> <animals> <option>Aardvark</option> <option>Bear</option> <option>Cat</option> </animals> </parent-component> </div>I am trying to get the selected option from child component (animals) to the parent component (parent-component). I am emitting the optionselected event from the child, but it looks like the parent component is not responding to that event, I mean the method test() is not being called at all. What am I doing wrong here?
Here is the JSFiddle Demo
Change style of first row in a table
I am trying to change the style of the first row in a table, the thing is that it doesn't apply correctly, i need to know if i can change directly the css with the specific tag accessing the first row of a table.
Basicly everytime i check a checkbox it should change the color of the header of my row to blue, and if it is unchecked not.
So i do this:
<div class="col-md-3"> <label class="checkbox-inline control-label col-md-10"><input v-model="hasHeader" type="checkbox">Header Row?</label> </div> <table class="table table-responsive"> <tbody> <tr v-for="(row,idx1) in tableRows" :class="{headerRowDefault: checkHeader}"> <td class="table-success" v-for="(col,idx2) in tableCols"><input v-model="table.tableGrid[idx1][idx2]" type="text" class="borderTbl" value="HEY"></td> </tr> </tbody> </table>my computed checkHeader method:
checkHeader (idx2) { alert('CHECKHEADER') if (this.hasHeader === true && idx2 === 0) { return true } else { return false } }is there a way i can on my checkbox trigger the change to the first row, i know i can apply a css style to the first row, but how can i do this on the trigger? any help?
Conditions in Vue.js 2
Cant find decision of easy task I have component:
<template> <div> <a v-for="social in socials" href="" > <i class="icon-mail"></i> </a> </div> </template> <script> export default{ mounted() { console.log('Component SocialButton.vue mounted'); }, data() { return { socials: [ { name: 'Email', type: 'mail', value: 'support@support.com', }, { name: 'Phone', type: 'bell', value: '000 000 000 000', }, { name: 'Facebook', type: 'facebook', value: 'facebook', }, { name: 'Twitter', type: 'twitter', value: 'twitter', }, { name: 'Pinterest', type: 'pinterest', value: 'pinterest', } ] } } } </script>So, if my "type" is equal "mail" or "bell" i should render class="hidden-md-down"
Or if type is equal another string, i should render class="social-button sb-{{type}} shape-none sb-dark"
Thx :)
Vue.js component prop without 2 way binding?
I found this question that is similar, but it did not explain the issue I am trying to solve for. (Using Vue.js 2)
I have an array of objects (users), that I display as a list. I want to open an "edit user" modal component, which needs to prefill the form values with the user data (exact parent object), but I do not want to edit the parent data until I click a save button that verifies the data before emitting an input event with the new values of the object.
I do not want to manually call out each property to create a new "clean" object (if I change the data type this is a headache), but Vue is adding its reactivity to the user object and therefore modifying the value in the component updates the parent value at the same time.
I also want to wait for the server to confirm a change is saved before emitting the input event; therefore the parent won't update until the data is confirmed on the server.
Is there a recommended pattern for non-reactively modifying props in components, instead using the emitted input event to update, as per the Vue component prop/event specs?
vuejs created hook: window/localstorage is not defined
I would like to save authenticated user to localstorage and load them into vuex on the next page load:
created () { let user = window.localStorage.getItem('user') if(user) { this.setUser(JSON.parse(user)) } }I thought that the created hook in my root component would be the right place for this. Unfortunately I get 'window is not defined'.
It works when I put it in the mounted hook instead. Unfortunately this is to late and shows the login page for a few ms.
Where should I put this logic?
How to render objects inside a string vue2
In Vue2, I have a string along the lines of the following in my component.
<template> <div><h1>Hello World</h1> <div v-html="testString"></div> </div> </template> <script> export default { name: "test-component", props: ['incoming'], data: function() { return { testString: ""; } }, created() { this.testString = this.incoming; } } </script>And then when I do the following (with all the imports done correctly)
<template> <text-component :incoming="mycontent"></text-component> </template> <script> import 'test-component' from './path/to/test-component.vue' export default { // etc, just presume this bit is right, it's only psudo code components: ['test-component'], data() { return { mycontent: '' }}, created() { this.mycontent="I just want to <router-link to='/home' v-html='Go Home'></router-link>" </script>So now I want the first template with testString to render the <router-link> as if I had put it in myself directly.
I've tried v-html and {{ }} , in my test-component but I think i'm missing something. I'm pretty sure in Vue1 I would use {{{ }}}.
Can anyone help out? Thanks.
How to bind v-for values to HTML attributes in Vue
I'm trying to attach the values I get from a v-for to attributes in the same tag but with no luck. Here's my code:
<label v-for="hashtag in hashtags" v-bind:title=`You can filter with {hashtag}` v-bind:data-value="hashtag" ></label>Basically the value goes to the title and data-value
Vue.js component not registering event
I am working on a small progress bar component using Vue.js. On the vm-progress component, the computed properties work as expected. However, on the three buttons, the increase_progress method is not being called. After installing the vue.js browser extension, no events are registered. I have tried adding debug and print statements without any luck.
<template> <div class="progbar"> <a class="app-task-title" style="text-align:center;">Text</a> <div class="app-bar"> <vm-progress :percentage="calc_percentage" :text-inside="true" :stroke-width="18" ></vm-progress> </div> <button v-on:click="increase_progress(5)" class="prog-bar-button" id="five_button" >+5m</button> <button @click="increase_progress(10)" class="prog-bar-button" id="ten_button" >+10m</button> <button v-on:click="increase_progress(30)" class="prog-bar-button" id="thirty_button" >+30m</button> </div> </template> <script type="text/javascript"> import Progress from 'vue-multiple-progress' export default { data (){ return { completed_minutes:0, total_minutes:60, percent_complete:0 }; }, components :{ 'vm-progress': Progress }, methods:{ increase_progress: function(minutes){ this.completed_minutes += minutes this.completed_minutes%=(this.total_minutes + 1); if((this.completed_minutes >= this.total_minutes) || (this.completed_minutes < 0)){ return } } }, computed:{ calc_percentage: function(){ return Math.round((100.0*this.completed_minutes)/this.total_minutes); } } } </script> <style > .progbar{ border: 2px solid #000000; height: auto; width: 90%; margin-right: 5%; margin-left: 5%; display: grid; grid-template-columns: 10% 81% 3% 3% 3%; grid-template-rows: 25px; align-items: center; justify-content: center; } .prog-bar-button{ font-family:Verdana; font-size: 10px; display: flex; align-items: center; justify-content: center; } .app-task-title{ grid-column-start: 1; grid-column-end: 2; font-size: 20px; text-align:center; vertical-align: middle; display:inline; } .app-bar{ grid-column-start: 2; grid-column-end: 3; align-self: center; } .progbar #five_button{ grid-column-start: 3; grid-column-end: 4; } .progbar #ten_button{ grid-column-start: 4; grid-column-end: 5; } .progbar #thirty_button{ grid-column-start: 5; grid-column-end: end; } </style>What is the worker.js file produced by vue.js?
Using Vue.js + vue.cli + webpack, I run npm run build, which creates a dist/ directory with my index.html and dist/static/ which contain all of the compiled JS, CSS, and other static assets. However, it also produces a file at e.g. dist/c93aff04b4ee373cfcc0.worker.js. Not loading this file does nothing to hinder the functionality of the application. Questions:
- What is this file and what does it do?
- Why is it so large (over half a Megabyte)
- Why isn't it in dist/static/ with the rest of the JavaScript that is produced by the compiler?
Why are Vue.js builds so huge?
I use Vue.js + vue-cli + webpack to create SPA's. The build sizes it produces are staggeringly large compared to the source I create. I recognize that a whole lot of library code is pulled in, but is there any way to optimize it further. As an example, my 200KB of templates and JavaScript, produces 2.1MB in JavaScript code alone! Is there anything that can be done to optimize this?
Vue.js + git build process
I use vue.js + vue-cli + webpack to build my applications. During development I will run npm run dev to have webpack continuously watch my sources, compile everything, and reload the browser. To create production build, I can simply run npm run build. I would like to do this in a way that when I make a git commit, if my sources have changed, the build is created automatically.
My current approach is to simply use git pre and post commit hooks to automatically run npm run build and add the built files to the commit. This has the following downsides:
- Even if other parts of the repo are changed, I re-run the build process for the Vue app, and it takes a very long time.
- It makes resolving merge conflicts nearly impossible.
- It creates a lot of cruft in the repo, ballooning its size
Typically I use a Vue.js frontend with a Django backend in the same repo, and deploy to Heroku or similar via a git push. What other methods are out there for accomplishing this task that don't have the above downsides?
A 'Beats Per Minute' calculator seems less accurate in Vue.js
I'm trying to create a 'beats per minute' (BPM) calculator, identical (for now) to the one you can find here. But for some reason, when I use the BPM calculator at that link on a test song, it gets within 1 BPM of the actual value of 85.94 within of 7 keypresses and just gets more accurate from there, ending within 0.05 of the actual BPM, whereas with my (essentially identically-coded) Vue.js version, it starts much higher (182-->126-->110) and goes down from there, but even after 60 keypresses it's still off by ~2 BPM, and after a full song, it was still off by about 0.37 BPM.
Here's the code for the plain-JavaScript version at that link:
var count = 0; var msecsFirst = 0; var msecsPrevious = 0; function ResetCount() { count = 0; document.TAP_DISPLAY.T_AVG.value = ""; document.TAP_DISPLAY.T_TAP.value = ""; document.TAP_DISPLAY.T_RESET.blur(); } function TapForBPM(e) { document.TAP_DISPLAY.T_WAIT.blur(); timeSeconds = new Date; msecs = timeSeconds.getTime(); if ((msecs - msecsPrevious) > 1000 * document.TAP_DISPLAY.T_WAIT.value) { count = 0; } if (count == 0) { document.TAP_DISPLAY.T_AVG.value = "First Beat"; document.TAP_DISPLAY.T_TAP.value = "First Beat"; msecsFirst = msecs; count = 1; } else { bpmAvg = 60000 * count / (msecs - msecsFirst); document.TAP_DISPLAY.T_AVG.value = Math.round(bpmAvg * 100) / 100; document.TAP_DISPLAY.T_WHOLE.value = Math.round(bpmAvg); count++; document.TAP_DISPLAY.T_TAP.value = count; } msecsPrevious = msecs; return true; } document.onkeypress = TapForBPM; // End -->And here's my version:
computed: { tappedOutBpm: function() { let totalElapsedSeconds = (this.timeOfLastBpmKeypress - this.timeOfFirstBpmKeypress) / 1000.0 let bpm = (this.numberOfTapsForBpm / totalElapsedSeconds) * 60.0 return Math.round(100*bpm)/100; }, }, methods: { tapForBPM: function() { let now = new Date; now = now.getTime(); // let now = window.performance.now() if (this.timeOfFirstBpmKeypress === 0 || now - this.timeOfLastBpmKeypress > 5000) { this.timeOfFirstBpmKeypress = now this.timeOfLastBpmKeypress = now this.numberOfTapsForBpm = 1 } else { this.timeOfLastBpmKeypress = now this.numberOfTapsForBpm++ } } }Vue $route is not defined in App.vue
I'm trying to get the name of the current route in my App.vue but all I get it's a null response.
In my App.vue:
export default { created() { console.log(this.$route.name) } }In my ./router/index.js:
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) const Hero = () => import ('../components/Hero.vue') const Home = () => import('../pages/Home.vue') const Videos = () => import ('../pages/Videos.vue') const VideosYoutube = () => import ('../pages/VideosYoutube.vue') const VideosFacebook = () => import ('../pages/VideosFacebook.vue') const VideosTwitter = () => import ('../pages/VideosTwitter.vue') const test = () => import('../pages/Example.vue') const routes = [{ name: 'home', path: '/', component: Home }, { name: 'videos', path: '/videos', components: { default: Videos, hero: Hero } }, { name: 'videos-youtube', path: '/videos/youtube', components: { default: VideosYoutube, hero: Hero } }, { name: 'videos-facebook', path: '/videos/facebook', components: { default: VideosFacebook, hero: Hero } }, { name: 'videos-twitter', path: '/videos/twitter', components: { default: VideosTwitter, hero: Hero } }, { name: 'test', path: '/test', component: test }] export default new Router({ mode: 'history', routes })I'm using Vue 2, Vue-Router 2 and webpack + babel es2015 presets.
It's weird because when I use the Vue Devtools, in my App component I can see the route object. On site.dev/videos:
And, finally, if I try to log this.$router I get an empty route like {name: null, meta: {…}, path: "/", hash: "", query: {…}, …}...
Here someone says to not use es6 style functions but it doesn't sound like a good solution and I don't really know how to do that.
How can I bind checkbox values to a null object in VueJS?
I'm trying to store all the selected checkbox items in a property.
This is a 'generic' property in one of my object models, it holds all different types of data.
This property is initialized as null, so Vue doesn't understand that it's supposed to be an array. So it only ever binds one checkbox value to this property.
When I initialize this property using [] to declare it as array, it works as intended. However the objects are passed down externally as JSON so initializing them as array is not an option.
var working = new Vue({ el: "#a", data: { options: ["Apple", "Banana", "Citrus"], answers: [], //<- I'm unable to do this in my scenario } }); var notWorking = new Vue({ el: "#b", data: { options: ["Apple", "Banana", "Citrus"], answers: null } });Here is a quick JSfiddle I made showcasing what I mean.
https://jsfiddle.net/ojvfy39p/12/
What adjustments must I make to the "Non working example" to achieve what the "Working example" does? I'
Listen to events from parent component in child and execute child’s method in vue without hub
There seems to be a lot of discussion around this topic such as Stackoverflow answer using hub, Stackoverflow answer using refs, so I really like to ask experts to provide for once a clear concise answer to this question. If the answer is also just not possible please state that!
Here is the scenario: There are two components, a parent and a child
<Parent> // There is a button here that can be clicked to emit an event using 'this.$emit()' <Child></Child> // The child listens and once hears the event, it does something </Parent> What to be achieved?Clicking the button in the Parent emits a certain event, the child will be constantly listening and once it hears the event it executes an action, such as calling a method of its own.
What is out there about this so far?Using a hub, in Vue Hub it is clearly stated this is for Non Parent-Child Communication, so what is the point in using it for a parent-child communication?
Using Refs, which is given as an end solution when it is not possible to use props and events. So why it is not possible with events at first place?
It seems to me the firing of an event and listening to it is only possible from child to parent, basically one way communication. The parent is able to emit an event but child component(s) are not able to capture the event. Why? I tried this and didn’t work:
In the parent component I have (triggered by clicking a button in the parent component):
methods: { generateCharts: function () { this.$emit('generate-charts') console.log('charts generated') }In the child component I have:
mounted () { this.parent.$on('generate-charts', function () { console.log('event captured') // Here nothing gets logged to the console }) }How to access the getter from another vuex module?
Within a vuex getter I know it is possible to access the state from another vuex module like so:
pages: (state, getters, rootState) => { console.log(rootState); }How can I access a getter from another vuex module instead of the state though?
I have another vuex module called filters that I need to access, I have tried this:
rootState.filters.activeFiltersWhere activeFilters is my getter but this does not work. using rootState.filters.getters.activeFilters also does not work.
How to send data from web to api?
Sorry for question but I don't understand that.
I have this:
<a @click.prevent="Submit(0)" href="#">NO</a> <a @click.prevent="Submit(1)" href="#">OK</a>Now in my vue method submit I want to post value 0 or 1 to my api and then store it in database. I have controller UserVote and model Vote. I am green here.
I must send it like this:
submit(value){ this.$http.post('/user/vote', JSON.stringify(WHAT HERE?)).then(response => { toastr.success(response.body.data[0]); if(response.body.redirect) { window.location.href = response.body.redirect; } }, response => { if(response.status == 422) { opinion = response.body.data; } else if(response.status == 401) { toastr.error(response.body.data.message); } }); }How my link should do? Where I post that? How I can upload that to db? I need just know, then I will be know everything.