Skip to content
This repository has been archived by the owner on Jan 24, 2020. It is now read-only.

Commit

Permalink
added token expiry intimation widget
Browse files Browse the repository at this point in the history
  • Loading branch information
mrellipse committed Dec 11, 2017
1 parent 57eb7ac commit 85e9ecf
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 7 deletions.
6 changes: 5 additions & 1 deletion src/server/Resources/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"search": "Search",
"secureContent": "Displaying secure content for registered users only",
"settings": "Settings",
"stranger" : "Stranger",
"stranger": "Stranger",
"success": "Success",
"update": "Update",
"verified": "Verified",
Expand Down Expand Up @@ -101,6 +101,10 @@
"site": {
"copyright": "© Copyright 2058, Toucan Corporation"
},
"token": {
"expiresAt": "Your login token expires at {0}",
"expired": "Your login token has expired"
},
"user": {
"updated": "User updated"
},
Expand Down
7 changes: 5 additions & 2 deletions src/server/Resources/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"search": "Chercher",
"secureContent": "Affichage de contenu sécurisé uniquement pour les utilisateurs enregistrés",
"settings": "Paramètres",
"stranger" : "Étranger",
"stranger": "Étranger",
"success": "Succès",
"update": "Mettre à jour",
"verified": "Vérifié",
Expand All @@ -43,7 +43,6 @@
"body": [
"<p>Quand la justice a-t-elle été aussi simple qu'un livre de règles?</p>",
"<p>Je pense que vous avez laissé vos sentiments personnels assombrir votre jugement.</p>"

]
},
"login": {
Expand Down Expand Up @@ -78,6 +77,10 @@
"title": "Page non trouvée",
"instruction": "Malheureuses circonstances"
},
"token": {
"expiresAt": "Votre jeton de connexion expire à{0}",
"expired": "Votre jeton de connexion a expiré"
},
"search": {
"title": "Résultats de recherche pour '{0}'",
"instruction": "Pas mis en œuvre"
Expand Down
1 change: 1 addition & 0 deletions src/ui/app/admin/layout/layout.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div>
<div class="row">
<status-bar :clear-after="5" locale-prefix="dict"></status-bar>
<token-expiry :info-timeout="300" :warn-timeout="60" :error-timeout="true" :logout="true"></token-expiry>
</div>
<div class="row">
<area-sidebar></area-sidebar>
Expand Down
3 changes: 2 additions & 1 deletion src/ui/app/admin/layout/layout.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { AreaSidebar } from '../sidebar/sidebar';
import { TokenExpiry } from '../../components/';

@Component({
components: { AreaSidebar },
components: { AreaSidebar, TokenExpiry },
template: require('./layout.html')
})
export class AreaLayout extends Vue {
Expand Down
1 change: 1 addition & 0 deletions src/ui/app/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export * from './notfound/notfound';
export * from './search/search';
export * from './status-bar/status-bar';
export * from './switch/switch';
export * from './token-expiry/token-expiry';
export * from './verify/verify';
121 changes: 121 additions & 0 deletions src/ui/app/components/token-expiry/token-expiry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { State } from 'vuex-class';

import { TokenHelper, PayloadMessageTypes } from '../../common/index';
import { IRouteMixinData, IRouterMixinData } from '../../mixins/mixin-router';
import { IPayloadMessage, IUser } from '../../model';
import { ICommonState, Store, StoreTypes } from '../../store';
import { AuthenticationService } from '../../services/index';

@Component({
props: ['infoTimeout', 'warnTimeout', 'errorTimeout', 'logout'],
template: `<div></div>`
})
export class TokenExpiry extends Vue {

private authenticationService: AuthenticationService = null;

@State((state: { common: ICommonState }) => state.common.user) user: IUser;

errorTimeout: boolean = this.errorTimeout;
infoTimeout: number = this.infoTimeout;
logout: boolean = this.logout;
warnTimeout: number = this.warnTimeout;

private infoHandle: number = null;
private warnHandle: number = null;
private errorHandle: number = null;

constructor() {
super();
}

created() {

this.authenticationService = new AuthenticationService(this.$store);

if (this.user.exp)
this.setHandlers(this.user.exp);

this.$store.watch((state: { common: ICommonState }) => state.common.user.exp, this.tokenExpiryChanged);
}

tokenExpiryChanged(tokenExpiresAt: Date) {
this.clearHandlers();

if (tokenExpiresAt)
this.setHandlers(tokenExpiresAt);
}

private clearHandlers() {

if (this.infoHandle)
window.clearTimeout(this.infoHandle);

if (this.warnHandle)
window.clearTimeout(this.warnHandle);

if (this.errorHandle)
window.clearTimeout(this.errorHandle);
}

private setHandlers(tokenExpiresAt: Date) {

if (tokenExpiresAt) {

let ms = tokenExpiresAt.getTime() - new Date().getTime();
let seconds = (ms / 1000);

if (this.infoTimeout && seconds > this.infoTimeout)
this.infoHandle = window.setTimeout(() => this.info(), ms - this.infoTimeout * 1000);

if (this.warnTimeout && seconds > this.warnTimeout)
this.warnHandle = window.setTimeout(() => this.warn(), ms - this.warnTimeout * 1000);

if (this.errorTimeout)
this.errorHandle = window.setTimeout(() => this.error(), tokenExpiresAt.getTime() - new Date().getTime());
}
}

private info() {

let msg: IPayloadMessage = {
text: this.$t('token.expiresAt', [this.user.exp.toLocaleString()]).toString(),
messageTypeId: PayloadMessageTypes.info
}

this.$store.dispatch(StoreTypes.updateStatusBar, msg);
}

private warn() {
let msg: IPayloadMessage = {
text: this.$t('token.expiresAt', [this.user.exp.toLocaleString()]).toString(),
messageTypeId: PayloadMessageTypes.warning
}

this.$store.dispatch(StoreTypes.updateStatusBar, msg);
}

private error() {

let msg: IPayloadMessage = {
text: this.$t('token.expired').toString(),
messageTypeId: PayloadMessageTypes.error
}

let logout = this.logout === undefined || this.logout === null ? true : this.logout;

if (logout)
this.authenticationService.logout()
.then(value => this.$store.dispatch(StoreTypes.updateUser, value))
.then(() => this.$store.dispatch(StoreTypes.updateStatusBar, msg))
.then(() => this.$router.push({ name: 'login' }));
else
this.$store.dispatch(StoreTypes.updateStatusBar, msg)
}

$router: IRouterMixinData;

$store: Store<{}>;
}
1 change: 1 addition & 0 deletions src/ui/app/root/layout/layout.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<div>
<div class="row">
<status-bar :clear-after="5" locale-prefix="dict"></status-bar>
<token-expiry :info-timeout="300" :warn-timeout="60" :error-timeout="true" :logout="true"></token-expiry>
</div>
<div class="row">
<area-sidebar></area-sidebar>
Expand Down
3 changes: 2 additions & 1 deletion src/ui/app/root/layout/layout.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { AreaSidebar } from '../sidebar/sidebar';
import { TokenExpiry } from '../../components/';

@Component({
components: { AreaSidebar },
components: { AreaSidebar, TokenExpiry },
template: require('./layout.html')
})
export class AreaLayout extends Vue {
Expand Down
2 changes: 1 addition & 1 deletion src/ui/npm-shrinkwrap.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "toucan.ui",
"version": "2.1.4",
"version": "2.1.5",
"description": "UI project for Toucan template",
"keywords": [
"vuejs",
Expand Down

0 comments on commit 85e9ecf

Please sign in to comment.