Skip to content

Commit c78b6f6

Browse files
committed
Improve CSRF handling
1 parent bdf13ab commit c78b6f6

File tree

1 file changed

+256
-0
lines changed

1 file changed

+256
-0
lines changed

examples/client_vue_auth.html

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="utf-8">
4+
<meta http-equiv="x-ua-compatible" content="ie=edge">
5+
<title>Vue.js CRUD application</title>
6+
<meta name="description" content="">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
9+
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.2.1/vue-router.js"></script>
10+
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.15.3/axios.js"></script>
11+
<script src="../lib/php_crud_api_transform.js"></script>
12+
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
13+
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css">
14+
<style>
15+
.logo {
16+
width: 50px;
17+
float: left;
18+
margin-right: 15px;
19+
}
20+
21+
.form-group {
22+
max-width: 500px;
23+
}
24+
25+
.actions {
26+
padding: 10px 0;
27+
}
28+
29+
.glyphicon-euro {
30+
font-size: 12px;
31+
}
32+
</style>
33+
</head>
34+
<body>
35+
36+
<div class="container">
37+
<header class="page-header">
38+
<div class="branding">
39+
<img src="https://vuejs.org/images/logo.png" alt="Logo" title="Home page" class="logo"/>
40+
<h1>Vue.js CRUD application</h1>
41+
</div>
42+
</header>
43+
<main id="app">
44+
<router-view></router-view>
45+
</main>
46+
</div>
47+
48+
<template id="post-list">
49+
<div>
50+
<div class="actions">
51+
<router-link class="btn btn-default" v-bind:to="{path: '/add-post'}">
52+
<span class="glyphicon glyphicon-plus"></span>
53+
Add post
54+
</router-link>
55+
</div>
56+
<div class="filters row">
57+
<div class="form-group col-sm-3">
58+
<label for="search-element">Filter</label>
59+
<input v-model="searchKey" class="form-control" id="search-element" requred/>
60+
</div>
61+
</div>
62+
<table class="table">
63+
<thead>
64+
<tr>
65+
<th>Content</th>
66+
<th class="col-sm-2">Actions</th>
67+
</tr>
68+
</thead>
69+
<tbody>
70+
<tr v-if="posts===null">
71+
<td colspan="4">Loading...</td>
72+
</tr>
73+
<tr v-else v-for="post in filteredposts">
74+
<td>
75+
<router-link v-bind:to="{name: 'post', params: {post_id: post.id}}">{{ post.content }}</router-link>
76+
</td>
77+
<td>
78+
<router-link class="btn btn-warning btn-xs" v-bind:to="{name: 'post-edit', params: {post_id: post.id}}">Edit</router-link>
79+
<router-link class="btn btn-danger btn-xs" v-bind:to="{name: 'post-delete', params: {post_id: post.id}}">Delete</router-link>
80+
</td>
81+
</tr>
82+
</tbody>
83+
</table>
84+
</div>
85+
</template>
86+
87+
<template id="add-post">
88+
<div>
89+
<h2>Add new post</h2>
90+
<form v-on:submit="createpost">
91+
<div class="form-group">
92+
<label for="add-content">Content</label>
93+
<textarea class="form-control" id="add-content" rows="10" v-model="post.content"></textarea>
94+
</div>
95+
<button type="submit" class="btn btn-primary">Create</button>
96+
<router-link class="btn btn-default" v-bind:to="'/'">Cancel</router-link>
97+
</form>
98+
</div>
99+
</template>
100+
101+
<template id="post">
102+
<div>
103+
<b>Content: </b>
104+
<div>{{ post.content }}</div>
105+
<br/>
106+
<span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span>
107+
<router-link v-bind:to="'/'">Back to post list</router-link>
108+
</div>
109+
</template>
110+
111+
<template id="post-edit">
112+
<div>
113+
<h2>Edit post</h2>
114+
<form v-on:submit="updatepost">
115+
<div class="form-group">
116+
<label for="edit-content">Content</label>
117+
<textarea class="form-control" id="edit-content" rows="3" v-model="post.content"></textarea>
118+
</div>
119+
<button type="submit" class="btn btn-primary">Save</button>
120+
<router-link class="btn btn-default" v-bind:to="'/'">Cancel</router-link>
121+
</form>
122+
</div>
123+
</template>
124+
125+
<template id="post-delete">
126+
<div>
127+
<h2>Delete post {{ post.id }}</h2>
128+
<form v-on:submit="deletepost">
129+
<p>The action cannot be undone.</p>
130+
<button type="submit" class="btn btn-danger">Delete</button>
131+
<router-link class="btn btn-default" v-bind:to="'/'">Cancel</router-link>
132+
</form>
133+
</div>
134+
</template>
135+
136+
<script>
137+
var posts = null;
138+
139+
var api = axios.create({
140+
baseURL: '../api.php',
141+
withCredentials: true
142+
});
143+
144+
function findpost (postId) {
145+
return posts[findpostKey(postId)];
146+
};
147+
148+
function findpostKey (postId) {
149+
for (var key = 0; key < posts.length; key++) {
150+
if (posts[key].id == postId) {
151+
return key;
152+
}
153+
}
154+
};
155+
156+
var List = Vue.extend({
157+
template: '#post-list',
158+
data: function () {
159+
return {posts: posts, searchKey: ''};
160+
},
161+
created: function () {
162+
var self = this;
163+
api.post('/',{username:"admin",password:"admin"}).then(function (response) {
164+
api.get('/posts').then(function (response) {
165+
posts = self.posts = php_crud_api_transform(response.data).posts;
166+
}).catch(function (error) {
167+
console.log(error);
168+
});
169+
}).catch(function (error) {
170+
console.log(error);
171+
});
172+
},
173+
computed: {
174+
filteredposts: function () {
175+
return this.posts.filter(function (post) {
176+
return this.searchKey=='' || post.content.indexOf(this.searchKey) !== -1;
177+
},this);
178+
}
179+
}
180+
});
181+
182+
var post = Vue.extend({
183+
template: '#post',
184+
data: function () {
185+
return {post: findpost(this.$route.params.post_id)};
186+
}
187+
});
188+
189+
var postEdit = Vue.extend({
190+
template: '#post-edit',
191+
data: function () {
192+
return {post: findpost(this.$route.params.post_id)};
193+
},
194+
methods: {
195+
updatepost: function () {
196+
var post = this.post;
197+
api.put('/posts/'+post.id,post).then(function (response) {
198+
console.log(response.data);
199+
}).catch(function (error) {
200+
console.log(error);
201+
});
202+
router.push('/');
203+
}
204+
}
205+
});
206+
207+
var postDelete = Vue.extend({
208+
template: '#post-delete',
209+
data: function () {
210+
return {post: findpost(this.$route.params.post_id)};
211+
},
212+
methods: {
213+
deletepost: function () {
214+
var post = this.post;
215+
api.delete('/posts/'+post.id).then(function (response) {
216+
console.log(response.data);
217+
}).catch(function (error) {
218+
console.log(error);
219+
});
220+
router.push('/');
221+
}
222+
}
223+
});
224+
225+
var Addpost = Vue.extend({
226+
template: '#add-post',
227+
data: function () {
228+
return {post: {content: '', user_id: 1, category_id: 1}}
229+
},
230+
methods: {
231+
createpost: function() {
232+
var post = this.post;
233+
api.post('/posts',post).then(function (response) {
234+
post.id = response.data;
235+
}).catch(function (error) {
236+
console.log(error);
237+
});
238+
router.push('/');
239+
}
240+
}
241+
});
242+
243+
var router = new VueRouter({routes:[
244+
{ path: '/', component: List},
245+
{ path: '/post/:post_id', component: post, name: 'post'},
246+
{ path: '/add-post', component: Addpost},
247+
{ path: '/post/:post_id/edit', component: postEdit, name: 'post-edit'},
248+
{ path: '/post/:post_id/delete', component: postDelete, name: 'post-delete'}
249+
]});
250+
app = new Vue({
251+
router:router
252+
}).$mount('#app')
253+
</script>
254+
255+
</body>
256+
</html>

0 commit comments

Comments
 (0)