Compare commits

...

7 Commits
1.7.0 ... 1.7.1

Author SHA1 Message Date
Thaum Rystra
45e9f491ff Merge branch 'feature-blacklist' 2018-04-02 14:27:24 +02:00
Thaum Rystra
742b26b0de Added rate limiting logging and an error page for hitting the rate limit on opening characters 2018-04-02 14:26:55 +02:00
Stefan Zermatten
164ba78c81 Added blacklist checks and rate limit logging
Needs testing
2018-03-12 09:22:04 +02:00
Thaum Rystra
e27211b24d Merge branch 'enhancement-154' 2018-03-03 20:13:03 +02:00
Thaum Rystra
30987752cc Hotfix - Remove localhost from image link on printed character sheet 2018-03-03 17:28:42 +02:00
Jacob
4e574c0f51 Added "clear" (reset to 0) button to resource cards 2018-02-24 14:49:42 +00:00
Jacob
80b195b7f7 Added reset button to resource cards 2018-02-24 14:42:41 +00:00
10 changed files with 110 additions and 8 deletions

View File

@@ -0,0 +1,9 @@
Blacklist = new Mongo.Collection("blacklist");
Schemas.Blacklist = new SimpleSchema({
userId: {
type: String,
},
});
Blacklist.attachSchema(Schemas.Blacklist);

View File

@@ -42,12 +42,21 @@ var ifKeyValid = function(apiKey, response, callback){
};
var isKeyValid = function(apiKey){
return !!Meteor.users.findOne({apiKey});
var user = Meteor.users.findOne({apiKey});
if (!user) return false;
var blackListed = Blacklist.findOne({userId: user._id});
return !blackListed;
};
var rateLimiter = new RateLimiter();
rateLimiter.addRule({apiKey: String}, 2, 10000);
var isRateLimited = function(apiKey){
return !rateLimiter.check({apiKey}).allowed;
const limited = !rateLimiter.check({apiKey}).allowed
if (limited) {
console.log(`Rate limit hit by API key ${apiKey}`);
return true;
} else {
return false;
}
};

View File

@@ -13,6 +13,11 @@ Router.plugin("ensureSignedIn", {
Router.plugin("dataNotFound", {notFoundTemplate: "notFound"});
var handleSubError = function(e){
Session.set("error", {reason: e.reason, href: location.href});
Router.go("/error");
};
Router.map(function() {
this.route("/", {
name: "home",
@@ -36,7 +41,9 @@ Router.map(function() {
path: "/character/:_id/",
waitOn: function(){
return [
subsManager.subscribe("singleCharacter", this.params._id),
subsManager.subscribe(
"singleCharacter", this.params._id, {onError: handleSubError}
),
];
},
action: function(){
@@ -52,7 +59,9 @@ Router.map(function() {
path: "/character/:_id/:urlName",
waitOn: function(){
return [
subsManager.subscribe("singleCharacter", this.params._id),
subsManager.subscribe(
"singleCharacter", this.params._id, {onError: handleSubError}
),
];
},
data: function() {
@@ -82,7 +91,9 @@ Router.map(function() {
path: "/character/:_id/:urlName/print",
waitOn: function(){
return [
subsManager.subscribe("singleCharacter", this.params._id),
subsManager.subscribe(
"singleCharacter", this.params._id, {onError: handleSubError}
),
];
},
data: function() {
@@ -153,4 +164,11 @@ Router.map(function() {
document.title = appName;
},
});
this.route("/error", {
name: "error",
onAfterAction: function() {
document.title = `${appName} - Error`;
},
});
});

View File

@@ -133,6 +133,12 @@
<div class="right clickable flex layout horizontal center">
{{title}}
</div>
<div class="layout horizontal center">
<div class="layout vertical">
<paper-button class="resourceResetMax" disabled={{cantIncrement}}>Reset</paper-button>
<paper-button class="resourceResetZero" disabled={{cantDecrement}}>Clear</paper-button>
</div>
</div>
</paper-material>
</div>
{{/if}}

View File

@@ -111,6 +111,17 @@ Template.resource.helpers({
});
Template.resource.events({
"click .resourceResetMax": function(event){
var modifier = {$set: {}};
modifier.$set[this.name + ".adjustment"] = 0;
Characters.update(this.char._id, modifier, {validate: false});
},
"click .resourceResetZero": function(event){
var base = Characters.calculate.attributeBase(this.char._id, this.name);
var modifier = {$set: {}};
modifier.$set[this.name + ".adjustment"] = -base;
Characters.update(this.char._id, modifier, {validate: false});
},
"click .resourceUp": function(event){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var base = Characters.calculate.attributeBase(this.char._id, this.name);

View File

@@ -18,7 +18,7 @@
<div class="page">
<div class="layout vertical" style="height: 100%;">
<div class="layout horizontal center" style="margin-bottom: 4mm">
<img src="http://localhost:3000/crown-dice-logo-cropped-transparent.png" style="width: 60px; margin-right: 2mm">
<img src="/crown-dice-logo-cropped-transparent.png" style="width: 60px; margin-right: 2mm">
<div class="characterName paper-font-title" style="margin-right: 4mm">
{{name}}
</div>

View File

@@ -0,0 +1,20 @@
<template name="error">
<app-header-layout has-scrolling-region fullbleed>
<app-header class="app-grey white-text" fixed>
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
</app-toolbar>
</app-header>
<div class="fit layout vertical center center-justified">
<div class="paper-font-subhead"
style="margin-left: 16px;
margin-right: 16px;
text-align: center;">
{{#if errorMessage}}
<div>{{errorMessage}}</div>
<paper-button class="try-again">Try Again</paper-button>
{{/if}}
</div>
</div>
</app-header-layout>
</template>

View File

@@ -0,0 +1,17 @@
Template.error.onRendered(function(){
const error = Session.get("error") || {};
if (error.href) window.history.replaceState("", "", error.href);
});
Template.error.helpers({
errorMessage: function(){
const error = Session.get("error") || {};
return error.reason;
},
});
Template.error.events({
"click .try-again": function(event, instance){
window.location.reload();
},
});

View File

@@ -0,0 +1,8 @@
logRateError = function(reply, ruleInput){
// reply = {allowed, timeToReset, numInvocationsLeft}
// ruleInput = {userId, clientAddress, type, name, connectionId}
console.log(
`Limit hit for ${ruleInput.type} "${ruleInput.name}" ` +
`by user ${ruleInput.userId} from ${ruleInput.clientAddress}`
);
}

View File

@@ -38,9 +38,13 @@ Meteor.publish("singleCharacter", function(characterId){
DDPRateLimiter.addRule({
name: "singleCharacter",
type: "subscription",
userId(){ return true; },
userId: null,
connectionId(){ return true; },
}, 8, 5000);
}, 8, 10000, function(reply, ruleInput){
if(!reply.allowed){
logRateError(reply, ruleInput);
}
});
Meteor.publish("singleCharacterName", function(characterId){
userId = this.userId;