Browse Source

Improve CSRF handling

Maurits van der Schee 7 years ago
parent
commit
c78b6f6c07
1 changed files with 256 additions and 0 deletions
  1. 256
    0
      examples/client_vue_auth.html

+ 256
- 0
examples/client_vue_auth.html View File

@@ -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>

Loading…
Cancel
Save