-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
37 changed files
with
1,845 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"engines": { | ||
"yarn": "1.x" | ||
}, | ||
"scripts": { | ||
"postinstall": "cd ./spec/rails_app && yarn && yarn install --check-files" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class AdminsController < ApplicationController | ||
before_action :set_admin, only: [:show] | ||
|
||
# GET /users | ||
def index | ||
render json: { | ||
users: Admin.all.as_json(include: :user) | ||
} | ||
end | ||
|
||
# GET /users/:id | ||
def show | ||
render json: @admin.as_json(include: :user) | ||
end | ||
|
||
private | ||
# Use callbacks to share common setup or constraints between actions. | ||
def set_admin | ||
@admin = Admin.find(params[:id]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
class SpaController < ApplicationController | ||
|
||
# GET /spa | ||
def index | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class UsersController < ApplicationController | ||
before_action :set_user, only: [:show] | ||
|
||
# GET /users | ||
def index | ||
render json: { | ||
users: User.all | ||
} | ||
end | ||
|
||
# GET /users/:id | ||
def show | ||
render json: @user | ||
end | ||
|
||
private | ||
# Use callbacks to share common setup or constraints between actions. | ||
def set_user | ||
@user = User.find(params[:id]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
<template> | ||
<div> | ||
<router-view /> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import Vue from 'vue' | ||
import VueRouter from 'vue-router' | ||
import VueMoment from 'vue-moment' | ||
import moment from 'moment-timezone' | ||
import VuePluralize from 'vue-pluralize' | ||
import axios from 'axios' | ||
import authStore from "./store/auth" | ||
import Top from './components/Top.vue' | ||
import DeviseTokenAuth from './components/DeviseTokenAuth.vue' | ||
import NotificationsIndex from './components/notifications/Index.vue' | ||
import SubscriptionsIndex from './components/subscriptions/Index.vue' | ||
const router = new VueRouter({ | ||
routes: [ | ||
{ path: '/', component: Top }, | ||
{ path: '/login', component: DeviseTokenAuth }, | ||
{ path: '/logout', component: DeviseTokenAuth, props: { isLogout: true } }, | ||
{ | ||
path: '/notifications', | ||
name: 'AuthenticatedUserNotificationsIndex', | ||
component: NotificationsIndex, | ||
props: () => ({ target: authStore.getters.currentUser }), | ||
meta: { requiresAuth: true } | ||
}, | ||
{ | ||
path: '/admins/notifications', | ||
name: 'AuthenticatedAdminNotificationsIndex', | ||
component: NotificationsIndex, | ||
props: () => ({ target: authStore.getters.currentUser.admin, targetApiPath: 'admins' }), | ||
meta: { requiresAuth: true } | ||
}, | ||
{ | ||
path: '/:target_type/:target_id/notifications', | ||
name: 'UnauthenticatedTargetNotificationsIndex', | ||
component: NotificationsIndex, | ||
props : true | ||
}, | ||
{ | ||
path: '/subscriptions', | ||
name: 'AuthenticatedUserSubscriptionsIndex', | ||
component: SubscriptionsIndex, | ||
props: () => ({ target: authStore.getters.currentUser }), | ||
meta: { requiresAuth: true } | ||
}, | ||
{ | ||
path: '/admins/subscriptions', | ||
name: 'AuthenticatedAdminSubscriptionsIndex', | ||
component: SubscriptionsIndex, | ||
props: () => ({ target: authStore.getters.currentUser.admin, targetApiPath: 'admins' }), | ||
meta: { requiresAuth: true } | ||
}, | ||
{ | ||
path: '/:target_type/:target_id/subscriptions', | ||
name: 'UnauthenticatedTargetSubscriptionsIndex', | ||
component: SubscriptionsIndex, | ||
props : true | ||
} | ||
] | ||
}) | ||
router.beforeEach((to, from, next) => { | ||
if (to.matched.some(record => record.meta.requiresAuth) && !authStore.getters.userSignedIn) { | ||
next({ path: '/login', query: { redirect: to.fullPath }}); | ||
} else { | ||
next(); | ||
} | ||
}) | ||
if (authStore.getters.userSignedIn) { | ||
for (var authHeader of Object.keys(authStore.getters.authHeaders)) { | ||
axios.defaults.headers.common[authHeader] = authStore.getters.authHeaders[authHeader]; | ||
} | ||
} | ||
Vue.use(VueRouter) | ||
Vue.use(VueMoment, { moment }) | ||
Vue.use(VuePluralize) | ||
export default { | ||
name: 'App', | ||
router | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
</style> |
83 changes: 83 additions & 0 deletions
83
spec/rails_app/app/javascript/components/DeviseTokenAuth.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
<template> | ||
<div id="login"> | ||
<h2>Log in</h2> | ||
<form class="new_user" @submit.prevent="login"> | ||
<div class="field"> | ||
<label for="user_email">Email</label><br /> | ||
<input v-model="loginParams.email" autofocus="autofocus" autocomplete="email" type="email" value="" name="user[email]" id="user_email" /> | ||
</div> | ||
<div class="field"> | ||
<label for="user_password">Password</label><br /> | ||
<input v-model="loginParams.password" autocomplete="current-password" type="password" name="user[password]" id="user_password" /> | ||
</div> | ||
<div class="actions"> | ||
<input type="submit" name="commit" value="Log in" data-disable-with="Log in" /> | ||
</div> | ||
</form> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import axios from 'axios' | ||
import authStore from "../store/auth" | ||
export default { | ||
name: 'DeviseTokenAuth', | ||
props: { | ||
isLogout: { | ||
type: Boolean, | ||
default: false | ||
} | ||
}, | ||
data () { | ||
return { | ||
loginParams: { | ||
email: "", | ||
password: "" | ||
} | ||
} | ||
}, | ||
mounted () { | ||
if (this.isLogout) { | ||
this.logout(); | ||
} | ||
}, | ||
methods: { | ||
login () { | ||
axios | ||
.post('/auth/sign_in', { email: this.loginParams.email, password: this.loginParams.password }) | ||
.then(response => { | ||
if (response.status == 200) { | ||
let authHeaders = {}; | ||
for (let authHeader of ['access-token', 'client', 'uid']) { | ||
authHeaders[authHeader] = response.headers[authHeader]; | ||
axios.defaults.headers.common[authHeader] = authHeaders[authHeader]; | ||
} | ||
authStore.commit('signIn', { user: response.data.data, authHeaders: authHeaders }); | ||
if (this.$route.query.redirect) { | ||
this.$router.push(this.$route.query.redirect); | ||
} else { | ||
this.$router.push('/'); | ||
} | ||
} | ||
}) | ||
.catch (error => { | ||
console.log("Authentication failed"); | ||
if (error.response.status == 401) { | ||
this.$router.go({path: this.$router.currentRoute.path}); | ||
} | ||
}) | ||
}, | ||
logout () { | ||
for (var authHeader of Object.keys(authStore.getters.authHeaders)) { | ||
delete axios.defaults.headers.common[authHeader]; | ||
} | ||
authStore.commit('signOut'); | ||
this.$router.push('/'); | ||
} | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<template> | ||
<div> | ||
<section> | ||
<h1>Authentecated User</h1> | ||
<div class="list_wrapper"> | ||
<div class="list_image"></div> | ||
<div class="list_description_wrapper"> | ||
<div class="list_description"> | ||
<div v-if="userSignedIn"> | ||
<span>{{ currentUser.name }}</span> · {{ currentUser.email }} · <router-link v-bind:to="{ path: '/logout' }">Logout</router-link><br> | ||
</div> | ||
<div v-else> | ||
<span>Not logged in</span> · <router-link v-bind:to="{ path: '/login' }">Login</router-link><br> | ||
</div> | ||
<router-link v-bind:to="{ name : 'AuthenticatedUserNotificationsIndex' }">Notifications</router-link> / | ||
<router-link v-bind:to="{ name : 'AuthenticatedUserSubscriptionsIndex' }">Subscriptions</router-link> | ||
</div> | ||
</div> | ||
</div> | ||
</section> | ||
|
||
<section> | ||
<h1>Listing Users</h1> | ||
<div v-for="user in users" :key="`${user.id}`" class="list_wrapper"> | ||
<div class="list_image"></div> | ||
<div class="list_description_wrapper"> | ||
<p class="list_description"> | ||
<span>{{ user.name }}</span> · {{ user.email }}<br> | ||
<router-link v-bind:to="{ name : 'UnauthenticatedTargetNotificationsIndex', params : { target_type: 'users', target_id: user.id, target: user }}">Notifications</router-link> / | ||
<router-link v-bind:to="{ name : 'UnauthenticatedTargetSubscriptionsIndex', params : { target_type: 'users', target_id: user.id, target: user }}">Subscriptions</router-link> | ||
</p> | ||
</div> | ||
</div> | ||
</section> | ||
|
||
<section> | ||
<h1>Authentecated User as Admin</h1> | ||
<div class="list_wrapper"> | ||
<div class="list_image"></div> | ||
<div class="list_description_wrapper"> | ||
<div class="list_description"> | ||
<div v-if="userSignedIn"> | ||
<span>{{ currentUser.name }}</span> · {{ currentUser.email }} · <span v-if="currentUser.admin">(admin)</span><span v-else>(not admin)</span><br> | ||
</div> | ||
<div v-else> | ||
<span>Not logged in</span> · <router-link v-bind:to="{ path: '/login' }">Login</router-link><br> | ||
</div> | ||
<router-link v-bind:to="{ name : 'AuthenticatedAdminNotificationsIndex' }">Notifications</router-link> / | ||
<router-link v-bind:to="{ name : 'AuthenticatedAdminSubscriptionsIndex' }">Subscriptions</router-link> | ||
</div> | ||
</div> | ||
</div> | ||
</section> | ||
|
||
<section> | ||
<h1>Listing Admins</h1> | ||
<div v-for="admin in admins" :key="`${admin.id}`" class="list_wrapper"> | ||
<div class="list_image"></div> | ||
<div class="list_description_wrapper"> | ||
<p class="list_description"> | ||
<span>{{ admin.user.name }}</span> · {{ admin.user.email }}<br> | ||
<router-link v-bind:to="{ name : 'UnauthenticatedTargetNotificationsIndex', params : { target_type: 'admins', target_id: admin.id, target: admin }}">Notifications</router-link> / | ||
<router-link v-bind:to="{ name : 'UnauthenticatedTargetSubscriptionsIndex', params : { target_type: 'admins', target_id: admin.id, target: admin }}">Subscriptions</router-link> | ||
</p> | ||
</div> | ||
</div> | ||
</section> | ||
</div> | ||
</template> | ||
|
||
<script> | ||
import axios from 'axios' | ||
import authStore from "../store/auth" | ||
export default { | ||
name: 'Top', | ||
data () { | ||
return { | ||
userSignedIn: authStore.getters.userSignedIn, | ||
currentUser: authStore.getters.currentUser, | ||
users: [], | ||
admins: [] | ||
} | ||
}, | ||
mounted () { | ||
axios | ||
.get('/users') | ||
.then(response => { | ||
this.users = response.data.users; | ||
this.admins = this.users | ||
.filter(user => user.admin) | ||
.map(user => Object.assign(Object.create(user.admin), { user: user })) | ||
}) | ||
} | ||
} | ||
</script> | ||
|
||
<style scoped> | ||
</style> |
Oops, something went wrong.