diff --git a/Gemfile b/Gemfile index bbc3a9e..c234f80 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'rails', '3.2.12' -gem 'sqlite3' +gem 'mysql2' gem 'jquery-rails' gem 'therubyracer' gem 'bcrypt-ruby', '~> 3.0.0' # To use ActiveModel's has_secure_password diff --git a/Gemfile.lock b/Gemfile.lock index 2b4bc11..776c09b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,6 +67,7 @@ GEM treetop (~> 1.4.8) mime-types (1.23) multi_json (1.7.3) + mysql2 (0.3.15) nokogiri (1.5.9) polyglot (0.3.3) rack (1.4.5) @@ -119,7 +120,6 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sqlite3 (1.3.7) therubyracer (0.11.4) libv8 (~> 3.11.8.12) ref @@ -146,6 +146,7 @@ DEPENDENCIES github-markdown hirb jquery-rails + mysql2 rails (= 3.2.12) rails-erd rb-readline (~> 0.4.2) @@ -153,7 +154,6 @@ DEPENDENCIES sanitize sass-rails (~> 3.2.3) simple_form - sqlite3 therubyracer uglifier (>= 1.0.3) webrick diff --git a/app/assets/images/lock-pin.png b/app/assets/images/lock-pin.png new file mode 100644 index 0000000..5f5a353 Binary files /dev/null and b/app/assets/images/lock-pin.png differ diff --git a/app/assets/images/lock.png b/app/assets/images/lock.png new file mode 100644 index 0000000..982792a Binary files /dev/null and b/app/assets/images/lock.png differ diff --git a/app/assets/images/pin.png b/app/assets/images/pin.png new file mode 100644 index 0000000..d3d8453 Binary files /dev/null and b/app/assets/images/pin.png differ diff --git a/app/assets/javascripts/app.js b/app/assets/javascripts/app.js index 666fd58..4b6806c 100644 --- a/app/assets/javascripts/app.js +++ b/app/assets/javascripts/app.js @@ -27,6 +27,7 @@ $(function(){ container: 'epic', textarea: 'epic-textarea', basePath: '/assets', + clientSideStorage: false, theme: { base: '/base/epiceditor.css', preview: '/preview/github.css', @@ -36,7 +37,7 @@ $(function(){ bar: true }, autogrow: { - minHeight: 500 + minHeight: 300 } }); try { diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 2c48026..3b02e62 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,3 +13,4 @@ //= require jquery_ujs //= require epiceditor //= require app +//= require moment \ No newline at end of file diff --git a/app/assets/javascripts/moment.js b/app/assets/javascripts/moment.js new file mode 100644 index 0000000..29e1cef --- /dev/null +++ b/app/assets/javascripts/moment.js @@ -0,0 +1,6 @@ +//! moment.js +//! version : 2.5.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function c(a,b){return function(c){return k(a.call(this,c),b)}}function d(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function e(){}function f(a){w(a),h(this,a)}function g(a){var b=q(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function h(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function i(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&qb.hasOwnProperty(b)&&(c[b]=a[b]);return c}function j(a){return 0>a?Math.ceil(a):Math.floor(a)}function k(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&s(a[d])!==s(b[d]))&&g++;return g+f}function p(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Tb[a]||Ub[b]||b}return a}function q(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=p(c),b&&(d[b]=a[c]));return d}function r(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}db[b]=function(e,f){var g,h,i=db.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=db().utc().set(d,a);return i.call(db.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function s(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function t(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function u(a){return v(a)?366:365}function v(a){return a%4===0&&a%100!==0||a%400===0}function w(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[jb]<0||a._a[jb]>11?jb:a._a[kb]<1||a._a[kb]>t(a._a[ib],a._a[jb])?kb:a._a[lb]<0||a._a[lb]>23?lb:a._a[mb]<0||a._a[mb]>59?mb:a._a[nb]<0||a._a[nb]>59?nb:a._a[ob]<0||a._a[ob]>999?ob:-1,a._pf._overflowDayOfYear&&(ib>b||b>kb)&&(b=kb),a._pf.overflow=b)}function x(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function y(a){return a?a.toLowerCase().replace("_","-"):a}function z(a,b){return b._isUTC?db(a).zone(b._offset||0):db(a).local()}function A(a,b){return b.abbr=a,pb[a]||(pb[a]=new e),pb[a].set(b),pb[a]}function B(a){delete pb[a]}function C(a){var b,c,d,e,f=0,g=function(a){if(!pb[a]&&rb)try{require("./lang/"+a)}catch(b){}return pb[a]};if(!a)return db.fn._lang;if(!m(a)){if(c=g(a))return c;a=[a]}for(;f0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&o(e,d,!0)>=b-1)break;b--}f++}return db.fn._lang}function D(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function E(a){var b,c,d=a.match(vb);for(b=0,c=d.length;c>b;b++)d[b]=Yb[d[b]]?Yb[d[b]]:D(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function F(a,b){return a.isValid()?(b=G(b,a.lang()),Vb[b]||(Vb[b]=E(b)),Vb[b](a)):a.lang().invalidDate()}function G(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(wb.lastIndex=0;d>=0&&wb.test(a);)a=a.replace(wb,c),wb.lastIndex=0,d-=1;return a}function H(a,b){var c,d=b._strict;switch(a){case"DDDD":return Ib;case"YYYY":case"GGGG":case"gggg":return d?Jb:zb;case"Y":case"G":case"g":return Lb;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?Kb:Ab;case"S":if(d)return Gb;case"SS":if(d)return Hb;case"SSS":if(d)return Ib;case"DDD":return yb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Cb;case"a":case"A":return C(b._l)._meridiemParse;case"X":return Fb;case"Z":case"ZZ":return Db;case"T":return Eb;case"SSSS":return Bb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Hb:xb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return xb;default:return c=new RegExp(P(O(a.replace("\\","")),"i"))}}function I(a){a=a||"";var b=a.match(Db)||[],c=b[b.length-1]||[],d=(c+"").match(Qb)||["-",0,0],e=+(60*d[1])+s(d[2]);return"+"===d[0]?-e:e}function J(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[jb]=s(b)-1);break;case"MMM":case"MMMM":d=C(c._l).monthsParse(b),null!=d?e[jb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[kb]=s(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=s(b));break;case"YY":e[ib]=s(b)+(s(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":e[ib]=s(b);break;case"a":case"A":c._isPm=C(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[lb]=s(b);break;case"m":case"mm":e[mb]=s(b);break;case"s":case"ss":e[nb]=s(b);break;case"S":case"SS":case"SSS":case"SSSS":e[ob]=s(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=I(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function K(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=M(a),a._w&&null==a._a[kb]&&null==a._a[jb]&&(f=function(b){var c=parseInt(b,10);return b?b.length<3?c>68?1900+c:2e3+c:c:null==a._a[ib]?db().weekYear():a._a[ib]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=Z(f(g.GG),g.W||1,g.E,4,1):(i=C(a._l),j=null!=g.d?V(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&ju(e)&&(a._pf._overflowDayOfYear=!0),c=U(e,0,a._dayOfYear),a._a[jb]=c.getUTCMonth(),a._a[kb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[lb]+=s((a._tzm||0)/60),l[mb]+=s((a._tzm||0)%60),a._d=(a._useUTC?U:T).apply(null,l)}}function L(a){var b;a._d||(b=q(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],K(a))}function M(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function N(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=C(a._l),h=""+a._i,i=h.length,j=0;for(d=G(a._f,g).match(vb)||[],b=0;b0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Yb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),J(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[lb]<12&&(a._a[lb]+=12),a._isPm===!1&&12===a._a[lb]&&(a._a[lb]=0),K(a),w(a)}function O(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function P(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a){var c,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(f=0;fg)&&(e=g,d=c));h(a,d||c)}function R(a){var b,c,d=a._i,e=Mb.exec(d);if(e){for(a._pf.iso=!0,b=0,c=Ob.length;c>b;b++)if(Ob[b][1].exec(d)){a._f=Ob[b][0]+(e[6]||" ");break}for(b=0,c=Pb.length;c>b;b++)if(Pb[b][1].exec(d)){a._f+=Pb[b][0];break}d.match(Db)&&(a._f+="Z"),N(a)}else a._d=new Date(d)}function S(b){var c=b._i,d=sb.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?R(b):m(c)?(b._a=c.slice(0),K(b)):n(c)?b._d=new Date(+c):"object"==typeof c?L(b):b._d=new Date(c)}function T(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function U(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function V(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function W(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function X(a,b,c){var d=hb(Math.abs(a)/1e3),e=hb(d/60),f=hb(e/60),g=hb(f/24),h=hb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",hb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,W.apply({},i)}function Y(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=db(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function Z(a,b,c,d,e){var f,g,h=U(a,0,1).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:u(a-1)+g}}function $(a){var b=a._i,c=a._f;return null===b?db.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=C().preparse(b)),db.isMoment(b)?(a=i(b),a._d=new Date(+b._d)):c?m(c)?Q(a):N(a):S(a),new f(a))}function _(a,b){db.fn[a]=db.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),db.updateOffset(this),this):this._d["get"+c+b]()}}function ab(a){db.duration.fn[a]=function(){return this._data[a]}}function bb(a,b){db.duration.fn["as"+a]=function(){return+this/b}}function cb(a){var b=!1,c=db;"undefined"==typeof ender&&(a?(gb.moment=function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)},h(gb.moment,c)):gb.moment=db)}for(var db,eb,fb="2.5.1",gb=this,hb=Math.round,ib=0,jb=1,kb=2,lb=3,mb=4,nb=5,ob=6,pb={},qb={_isAMomentObject:null,_i:null,_f:null,_l:null,_strict:null,_isUTC:null,_offset:null,_pf:null,_lang:null},rb="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,sb=/^\/?Date\((\-?\d+)/i,tb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,ub=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,vb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,wb=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,xb=/\d\d?/,yb=/\d{1,3}/,zb=/\d{1,4}/,Ab=/[+\-]?\d{1,6}/,Bb=/\d+/,Cb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Db=/Z|[\+\-]\d\d:?\d\d/gi,Eb=/T/i,Fb=/[\+\-]?\d+(\.\d{1,3})?/,Gb=/\d/,Hb=/\d\d/,Ib=/\d{3}/,Jb=/\d{4}/,Kb=/[+-]?\d{6}/,Lb=/[+-]?\d+/,Mb=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Nb="YYYY-MM-DDTHH:mm:ssZ",Ob=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],Pb=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Qb=/([\+\-]|\d\d)/gi,Rb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Sb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Tb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Ub={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Vb={},Wb="DDD w W M D d".split(" "),Xb="M D H h m s w W".split(" "),Yb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return k(this.year()%100,2)},YYYY:function(){return k(this.year(),4)},YYYYY:function(){return k(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+k(Math.abs(a),6)},gg:function(){return k(this.weekYear()%100,2)},gggg:function(){return k(this.weekYear(),4)},ggggg:function(){return k(this.weekYear(),5)},GG:function(){return k(this.isoWeekYear()%100,2)},GGGG:function(){return k(this.isoWeekYear(),4)},GGGGG:function(){return k(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return s(this.milliseconds()/100)},SS:function(){return k(s(this.milliseconds()/10),2)},SSS:function(){return k(this.milliseconds(),3)},SSSS:function(){return k(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+":"+k(s(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+k(s(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Zb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Wb.length;)eb=Wb.pop(),Yb[eb+"o"]=d(Yb[eb],eb);for(;Xb.length;)eb=Xb.pop(),Yb[eb+eb]=c(Yb[eb],2);for(Yb.DDDD=c(Yb.DDD,3),h(e.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=db.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=db([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return Y(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),db=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=c,g._f=d,g._l=e,g._strict=f,g._isUTC=!1,g._pf=b(),$(g)},db.utc=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=c,g._f=d,g._strict=f,g._pf=b(),$(g).utc()},db.unix=function(a){return db(1e3*a)},db.duration=function(a,b){var c,d,e,f=a,h=null;return db.isDuration(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=tb.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:s(h[kb])*c,h:s(h[lb])*c,m:s(h[mb])*c,s:s(h[nb])*c,ms:s(h[ob])*c}):(h=ub.exec(a))&&(c="-"===h[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},f={y:e(h[2]),M:e(h[3]),d:e(h[4]),h:e(h[5]),m:e(h[6]),s:e(h[7]),w:e(h[8])}),d=new g(f),db.isDuration(a)&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},db.version=fb,db.defaultFormat=Nb,db.updateOffset=function(){},db.lang=function(a,b){var c;return a?(b?A(y(a),b):null===b?(B(a),a="en"):pb[a]||C(a),c=db.duration.fn._lang=db.fn._lang=C(a),c._abbr):db.fn._lang._abbr},db.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),C(a)},db.isMoment=function(a){return a instanceof f||null!=a&&a.hasOwnProperty("_isAMomentObject")},db.isDuration=function(a){return a instanceof g},eb=Zb.length-1;eb>=0;--eb)r(Zb[eb]);for(db.normalizeUnits=function(a){return p(a)},db.invalid=function(a){var b=db.utc(0/0);return null!=a?h(b._pf,a):b._pf.userInvalidated=!0,b},db.parseZone=function(a){return db(a).parseZone()},h(db.fn=f.prototype,{clone:function(){return db(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=db(this).utc();return 00:!1},parsingFlags:function(){return h({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=F(this,a||db.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,-1),this},diff:function(a,b,c){var d,e,f=z(a,this),g=6e4*(this.zone()-f.zone());return b=p(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-db(this).startOf("month")-(f-db(f).startOf("month")))/d,e-=6e4*(this.zone()-db(this).startOf("month").zone()-(f.zone()-db(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:j(e)},from:function(a,b){return db.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(db(),a)},calendar:function(){var a=z(db(),this).startOf("day"),b=this.diff(a,"days",!0),c=-6>b?"sameElse":-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.lang().calendar(c,this))},isLeapYear:function(){return v(this.year())},isDST:function(){return this.zone()+db(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+db(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+z(a,this).startOf(b)},min:function(a){return a=db.apply(null,arguments),this>a?this:a},max:function(a){return a=db.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=I(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&l(this,db.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?db(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return t(this.year(),this.month())},dayOfYear:function(a){var b=hb((db(this).startOf("day")-db(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(a){var b=Y(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=Y(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=Y(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=p(a),this[a]()},set:function(a,b){return a=p(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=C(b),this)}}),eb=0;eb e + puts "---" + puts "WARNING: registration mail failed for user #{@user.name}, #{@user.email}" + puts e.message + puts "---" + flash[:alert] = "Registration mail failed. Please contact us in-game." + end + flash[:notice] = "Successfully signed up! Check your email!" + redirect_to edit_user_path(@user) + else + flash[:alert] = "Something went wrong" + render action: "new" + end + @user.email_token = SecureRandom.hex(16) + else + flash[:alert] = "Token invalid for this username" + render action: "new" end - begin - RedstonerMailer.register_mail(@user, minecraftpw).deliver - RedstonerMailer.register_info_mail(@user, minecraftpw).deliver - rescue => e - puts "---" - puts "WARNING: registration mail failed for user #{@user.name}, #{@user.email}" - puts e.message - puts "---" - flash[:alert] = "Registration mail failed. Please contact us in-game." - end - flash[:notice] = "Successfully signed up! Check your email!" - redirect_to edit_user_path(@user) else - flash[:alert] = "Something went wrong" - render action: "new" + flash[:alert] = "Error. Your username is not correct or Mojang's servers are down." + render action: new + return end end end @@ -129,10 +143,10 @@ require 'open-uri' youtube = get_youtube(userdata[:youtube]) userdata[:youtube] = youtube[:channel] userdata[:youtube_channelname] = youtube[:channel_name] - flash[:alert] = "Couldn't find a YouTube channel by that name, are you sure it's correct?" unless youtube[:is_correct?] + flash[:alert] = "Couldn't find a YouTube channel with that name, are you sure it's correct?" unless youtube[:is_correct?] end if @user.update_attributes(userdata) - flash[:notice] = 'Profile updated.' + flash[:notice] = 'Profile updated.' else flash[:alert] = "There was a problem while updating the profile" render action: "edit" @@ -158,7 +172,7 @@ require 'open-uri' def unban @user = User.find(params[:id]) if mod? && current_user.role >= @user.role - @user.role = Role.get :default + @user.role = Role.get :normal flash[:notice] = "\"#{@user.name}\" has been unbanned!" else flash[:alert] = "You are not allowed to unban this user!" @@ -212,4 +226,13 @@ require 'open-uri' redirect_to old_user end + + + private + + def validate_token(uuid, email, token) + user_token = RegisterToken.where(uuid: uuid, email: email).first + user_token && user_token.token == token + end + end \ No newline at end of file diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 9583b18..f0f5475 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,54 +1,6 @@ module UsersHelper require "open-uri" - def avatar_url(user_id, size) - u = User.find_by_id(user_id) - u.nil? ? ign = :char : ign = u.ign - return "https://minotar.net/helm/#{CGI.escape(ign)}/#{CGI.escape(size.to_s)}" - end - - def uses_mc_password?(ign, password) - query = { - user: ign, - password: password, - version: 9999 #just something high so it won't fail with "Old version" - }.to_query - begin - #check if this user is an idiot and uses their mc password. - mclogin = open("https://login.minecraft.net/?#{query}", :read_timeout => 1).read - rescue - puts "---" - puts "ERROR: failed to check mc password for '#{ign}'. Login servers down?" - puts "---" - end - !!mclogin.downcase.include?(ign.downcase) - end - - def haspaid?(ign) - query = {user: ign}.to_query - begin - response = open("https://minecraft.net/haspaid.jsp?#{query}", :read_timeout => 1).read - rescue - puts "---" - puts "ERROR: failed to check for premium account for '#{ign}'. Minecraft servers down?" - puts "---" - response = "true" - end - !(response.casecmp("false") == 0) - end - - def correct_case?(ign) - begin - http = Net::HTTP.start("skins.minecraft.net") - skin = http.get("/MinecraftSkins/#{CGI.escape(ign)}.png") - http.finish - rescue - puts "---" - puts "ERROR: failed to get skin status code for '#{ign}'. Skin servers down?" - puts "---" - end - skin.code != "404" - end def get_youtube(yt_name) yt = {channel: yt_name} @@ -67,10 +19,4 @@ require "open-uri" yt end - def link_user(user, html_options = {}) - html_options[:class] = "role #{user.role.name} #{html_options[:class]}" - link_to(user.name, user, html_options) - end - - end \ No newline at end of file diff --git a/app/mailers/redstoner_mailer.rb b/app/mailers/redstoner_mailer.rb index d987f8b..62c0741 100644 --- a/app/mailers/redstoner_mailer.rb +++ b/app/mailers/redstoner_mailer.rb @@ -1,17 +1,17 @@ class RedstonerMailer < ActionMailer::Base default from: "info@redstoner.com" - default reply_to: "redstonerserver@gmail.com" + default reply_to: "redstonerserver+website@gmail.com" def register_mail(user, uses_mc_pass) @user = user @mcpw = uses_mc_pass - mail(to: @user.email, subject: "Registration on Redstoner.com", from: "info@redstoner.com", reply_to: "redstonerserver@gmail.com") + mail(to: @user.email, subject: "Registration on Redstoner.com", from: "info@redstoner.com", reply_to: "redstonerserver+website@gmail.com") end def register_info_mail(user, uses_mc_pass) @user = user @mcpw = uses_mc_pass - mail(to: "redstonerserver@gmail.com", subject: "#{@user.name} registered on Redstoner.com", from: "info@redstoner.com", reply_to: "redstonerserver@gmail.com") + mail(to: "redstonerserver@gmail.com", subject: "#{@user.name} registered on Redstoner.com", from: "info@redstoner.com", reply_to: "redstonerserver+website@gmail.com") end end \ No newline at end of file diff --git a/app/models/forum.rb b/app/models/forum.rb index 4ace5db..4d04427 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -13,4 +13,12 @@ class Forum < ActiveRecord::Base def group forumgroup end -end + + def can_read?(user) + group.can_read?(user) && (role_read.nil? || (!user.nil? && user.role >= role_read)) + end + + def can_write?(user) + group.can_read?(user) && can_read?(user) && (role_write.nil? || (!user.nil? && user.role >= role_write)) + end +end \ No newline at end of file diff --git a/app/models/forumgroup.rb b/app/models/forumgroup.rb index 55577f5..a3f8e2b 100644 --- a/app/models/forumgroup.rb +++ b/app/models/forumgroup.rb @@ -12,4 +12,12 @@ class Forumgroup < ActiveRecord::Base def to_s name end + + def can_read?(user) + role_read.nil? || (!user.nil? && user.role >= role_read) + end + + def can_write?(user) + !user.nil? && can_read?(user) && user.confirmed? && (role_write.nil? || user.role >= role_write) + end end diff --git a/app/models/forumthread.rb b/app/models/forumthread.rb index 7a5e9b1..7fd34a5 100644 --- a/app/models/forumthread.rb +++ b/app/models/forumthread.rb @@ -2,11 +2,15 @@ class Forumthread < ActiveRecord::Base belongs_to :forum belongs_to :user_author, class_name: "User", foreign_key: "user_author_id" belongs_to :user_editor, class_name: "User", foreign_key: "user_editor_id" + has_many :threadreplies attr_accessible :title, :content, :sticky, :locked, :user_author, :user_editor, :forum - validates_presence_of :title + validates_presence_of :title, :author, :forum validates_presence_of :content + validates_length_of :content, in: 5..10000 + + accepts_nested_attributes_for :threadreplies def to_s title @@ -23,4 +27,16 @@ class Forumthread < ActiveRecord::Base def editor @editor ||= user_editor end + + def replies + threadreplies + end + + def can_read?(user) + forum.can_read?(user) + end + + def can_write?(user) + forum.can_write?(user) && (!locked? || mod?) + end end \ No newline at end of file diff --git a/app/models/register_token.rb b/app/models/register_token.rb new file mode 100644 index 0000000..36c0cd1 --- /dev/null +++ b/app/models/register_token.rb @@ -0,0 +1,2 @@ +class RegisterToken < ActiveRecord::Base +end \ No newline at end of file diff --git a/app/models/role.rb b/app/models/role.rb index 7785c41..3c28de9 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -25,20 +25,24 @@ class Role < ActiveRecord::Base elsif role.is_a?(Symbol) self <=> Role.find_by_name(role) else - raise "Cannot compare Role with #{role.class}" + self.to_i <=> role end end - def self.all_until (role) - Role.all.select do |r| + def self.all_to (role) + Role.order(:value).select do |r| r <= role end end def self.all_from(role) - Role.all.select do |r| + Role.order(:value).select do |r| r >= role end end + def self.all_from_to(from, to) + Role.order(:value).select {|r| r >= from}.select {|r| r <= to} + end + end \ No newline at end of file diff --git a/app/models/threadreply.rb b/app/models/threadreply.rb new file mode 100644 index 0000000..03b28d3 --- /dev/null +++ b/app/models/threadreply.rb @@ -0,0 +1,22 @@ +class Threadreply < ActiveRecord::Base + belongs_to :forumthread + belongs_to :user_author, class_name: "User", foreign_key: "user_author_id" + belongs_to :user_editor, class_name: "User", foreign_key: "user_editor_id" + + attr_accessible :title, :content, :sticky, :locked, :user_author, :user_editor, :forumthread + + validates_presence_of :content + validates_length_of :content, in: 2..10000 + + def author + @author ||= if self.user_author.present? + user_author + else + User.first + end + end + + def editor + @editor ||= user_editor + end +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index 4a7df1e..601ce01 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,34 +1,43 @@ class User < ActiveRecord::Base include UsersHelper + include Rails.application.routes.url_helpers + belongs_to :role - attr_accessible :name, :password, :password_confirmation, :ign, :email, :confirm_code, :about, :last_ip, :skype, :skype_public, :youtube, :youtube_channelname, :twitter, :last_login, :role, :role_id + attr_accessible :uuid, :confirmed, :name, :password, :password_confirmation, :ign, :email, :email_token, :about, :last_ip, :skype, :skype_public, :youtube, :youtube_channelname, :twitter, :last_seen, :role, :role_id has_secure_password - before_validation :strip_whitespaces + before_validation :strip_whitespaces, :set_uuid, :set_name, :set_role, :set_email_token - validates_presence_of :password, :password_confirmation, :confirm_code, :on => :create + validates_presence_of :password, :password_confirmation, :email_token, :on => :create validates_presence_of :name, :email, :ign validates_length_of :password, in: 8..256, :on => :create - validates_length_of :name, in: 3..20 + validates_length_of :name, in: 2..30 validates_length_of :about, maximum: 5000 - validates_length_of :ign, minimum: 2, maximum: 100 + validates_length_of :ign, minimum: 2, maximum: 16 - validates :email, uniqueness: {case_sensitive: false}, format: {with: /^\S+@\S+\.[a-z]{2,}$/i, message: "That doesn't look like an email adress."} - validates :name, uniqueness: {case_sensitive: false}, format: {with: /^[a-z\d\-_ ]+$/i, message: "Allowed characters: a-z0-9, dashes, underscores and spaces"} + validates :email, uniqueness: {case_sensitive: false}, format: {with: /^.+@.+\..{2,}$/i, message: "That doesn't look like an email adress."} validates :ign, uniqueness: {case_sensitive: false}, format: {with: /^[a-z\d_]+$/i, message: "That is probably not your username."} - validate :ign_is_not_skull, :ign_has_paid, :ign_has_correct_case - validate :ign_is_not_mojang, on: :create + validate :ign_has_paid has_many :blogposts has_many :comments + # foo.bar.is?(current_user) def is? (user) self == user end + def donor? + !!self.donor + end + + def confirmed? + !!self.confirmed + end + #roles def disabled? !!(self.role == :disabled) @@ -38,20 +47,8 @@ class User < ActiveRecord::Base !!(self.role == :banned) end - def unconfirmed? - !!(self.role == :unconfirmed) - end - - def confirmed? - !!(self.role > :unconfirmed) - end - - def default? - !!(self.role >= :default) - end - - def donor? - !!(self.role >= :donor) + def normal? + !!(self.role >= :normal) end def mod? @@ -66,26 +63,124 @@ class User < ActiveRecord::Base !!(self.role >= :superadmin) end - private - def ign_is_not_skull - errors.add(:ign, "Good one...") if ["MHF_Blaze", "MHF_CaveSpider", "MHF_Chicken", "MHF_Cow", "MHF_Enderman", "MHF_Ghast", "MHF_Golem", "MHF_Herobrine", "MHF_LavaSlime", "MHF_MushroomCow", "MHF_Ocelot", "MHF_Pig", "MHF_PigZombie", "MHF_Sheep", "MHF_Slime", "MHF_Spider", "MHF_Squid", "MHF_Villager", "MHF_Cactus", "MHF_Cake", "MHF_Chest", "MHF_Melon", "MHF_OakLog", "MHF_Pumpkin", "MHF_TNT", "MHF_TNT2", "MHF_ArrowUp", "MHF_ArrowDown", "MHF_ArrowLeft", "MHF_ArrowRight", "MHF_Exclamation", "MHF_Question"].include?(self.ign) + def avatar_url(size) + return "https://minotar.net/helm/#{CGI.escape(self.ign)}/#{CGI.escape(size.to_s)}" end - def ign_is_not_mojang - if self.ign.start_with?("mojang_secret_ign_") - self.ign = self.ign[18..-1] - else - errors.add(:ign, "If that's really you, contact us in-game.") if ["mollstam", "carlmanneh", "MinecraftChick", "Notch", "jeb_", "xlson", "jonkagstrom", "KrisJelbring", "marc", "Marc_IRL", "MidnightEnforcer", "YoloSwag4Lyfe", "EvilSeph", "Grumm", "Dinnerbone", "geuder", "eldrone", "JahKob", "BomBoy", "MansOlson", "pgeuder", "91maan90", "vubui", "PoiPoiChen", "mamirm", "eldrone", "_tomcc"].include?(self.ign) + + + #check if this user is an idiot and uses their mc password. + def uses_mc_password?(password) + uri = URI.parse("https://authserver.mojang.com/authenticate") + http = Net::HTTP.new(uri.host, uri.port) + http.open_timeout = 5 + http.read_timeout = 20 + http.use_ssl = true + + payload = { agent: { name: "Minecraft", version: 1 }, username: self.email, password: password } + begin + response = http.post(uri.request_uri, payload.to_json, "Content-Type" => "application/json").code + if response.code == "200" + return true + else + payload[:username] = self.ign + return http.post(uri.request_uri, payload.to_json, "Content-Type" => "application/json").code == "200" + end + rescue => e + puts "---" + puts "ERROR: failed to check mc password for '#{self.uuid}'. Login servers down?" + puts e.message + puts "---" + return false end end - def ign_has_paid - errors.add(:ign, "'#{self.ign}' is not a valid account!") unless haspaid?(self.ign) + def haspaid? + begin + response = open("https://sessionserver.mojang.com/session/minecraft/profile/#{CGI.escape(self.uuid)}", read_timeout: 0.5) + if response.status[0] == "200" + session_profile = JSON.load(response.read) + if session_profile["legacy"] == true + return open("https://minecraft.net/haspaid.jsp?#{{user: self.ign}.to_query}", read_timeout: 0.5).read == "true" + else + return true + end + elsif response.status[0] == "204" + return false + else + puts "---" + puts "ERROR: unexpected response code while checking '#{self.uuid}' for premium account" + puts "code: #{reponse.status}, body: '#{reponse.read}'" + puts "---" + end + rescue => e + puts "---" + puts "ERROR: failed to check for premium account for '#{self.uuid}'. Minecraft servers down?" + puts e.message + puts "---" + end + # mojang servers have trouble + return true end - def ign_has_correct_case - errors.add(:ign, "The IGN is case-sensitive. Please correct '#{self.ign}'.") unless correct_case?(self.ign) + # def correct_case?(ign) + # begin + # http = Net::HTTP.start("skins.minecraft.net") + # skin = http.get("/MinecraftSkins/#{CGI.escape(ign)}.png") + # http.finish + # rescue + # puts "---" + # puts "ERROR: failed to get skin status code for '#{ign}'. Skin servers down?" + # puts "---" + # end + # skin.code != "404" + # end + + def get_profile + uri = URI.parse("https://api.mojang.com/profiles") + http = Net::HTTP.new(uri.host, uri.port) + http.open_timeout = 5 + http.read_timeout = 20 + http.use_ssl = true + + payload = { agent: "Minecraft", name: self.ign } + begin + response = http.post(uri.request_uri, payload.to_json, "Content-Type" => "application/json") + if response.code == "200" + return JSON.load(response.body)["profiles"][0] + end + rescue => e + puts "----" + puts "Failed to get mojang profile for #{self.ign}" + puts e.message + puts "----" + return nil + end + end + + + + + + private + + def set_uuid + if !self.uuid.present? + # idk + end + end + + def set_name + self.name ||= self.ign + end + + def set_role + self.role ||= Role.get(:normal) + end + + def ign_has_paid + errors.add(:ign, "'#{self.ign}' is not a valid account!") unless self.haspaid? end def strip_whitespaces @@ -97,4 +192,20 @@ class User < ActiveRecord::Base self.youtube.strip! if self.youtube self.twitter.strip! if self.twitter end + + def set_email_token + self.email_token = SecureRandom.hex(16) + end + + # def ign_is_not_skull + # errors.add(:ign, "Good one...") if ["MHF_Blaze", "MHF_CaveSpider", "MHF_Chicken", "MHF_Cow", "MHF_Enderman", "MHF_Ghast", "MHF_Golem", "MHF_Herobrine", "MHF_LavaSlime", "MHF_MushroomCow", "MHF_Ocelot", "MHF_Pig", "MHF_PigZombie", "MHF_Sheep", "MHF_Slime", "MHF_Spider", "MHF_Squid", "MHF_Villager", "MHF_Cactus", "MHF_Cake", "MHF_Chest", "MHF_Melon", "MHF_OakLog", "MHF_Pumpkin", "MHF_TNT", "MHF_TNT2", "MHF_ArrowUp", "MHF_ArrowDown", "MHF_ArrowLeft", "MHF_ArrowRight", "MHF_Exclamation", "MHF_Question"].include?(self.ign) + # end + + # def ign_is_not_mojang + # if self.ign.start_with?("mojang_secret_ign_") + # self.ign = self.ign[18..-1] + # else + # errors.add(:ign, "If that's really you, contact us in-game.") if ["mollstam", "carlmanneh", "MinecraftChick", "Notch", "jeb_", "xlson", "jonkagstrom", "KrisJelbring", "marc", "Marc_IRL", "MidnightEnforcer", "YoloSwag4Lyfe", "EvilSeph", "Grumm", "Dinnerbone", "geuder", "eldrone", "JahKob", "BomBoy", "MansOlson", "pgeuder", "91maan90", "vubui", "PoiPoiChen", "mamirm", "eldrone", "_tomcc"].include?(self.ign) + # end + # end end \ No newline at end of file diff --git a/app/views/blogposts/index.html.erb b/app/views/blogposts/index.html.erb index b9b2a7b..e2c989b 100644 --- a/app/views/blogposts/index.html.erb +++ b/app/views/blogposts/index.html.erb @@ -1,19 +1,20 @@ <%= link_to 'Make new Post', new_blogpost_path, class: "btn blue" if mod? %>
<% @posts.each do |p| %> -
-
-

<%= link_to truncate(p.title, length: 60, omission: " …"), p %>

- - <%= link_to pluralize(p.comments.count, "Comment"), p %> - +
+ <%= link_to(image_tag(p.author.avatar_url(64), class: "avatar"), p.author, title: p.author.ign) %> +
+ <%= render partial: "users/username", locals: { user: p.author } %> + + <%= link_to pluralize(p.comments.count, "Comment"), p %> + +
+
+
+

<%= link_to truncate(p.title, length: 60, omission: " …"), p %>

+ <%= Sanitize.clean(GitHub::Markdown.render_gfm(p.content), Sanitize::Config::RELAXED).html_safe %> +
+
- -
- <%= Sanitize.clean(GitHub::Markdown.render_gfm(p.content), Sanitize::Config::RELAXED).html_safe %> -
-
<% end %>
diff --git a/app/views/blogposts/show.html.erb b/app/views/blogposts/show.html.erb index 60a9589..e860717 100644 --- a/app/views/blogposts/show.html.erb +++ b/app/views/blogposts/show.html.erb @@ -1,20 +1,20 @@ -
-
-

<%= @post.title %>

+
+ <%= link_to(image_tag(@post.author.avatar_url(64), class: "avatar"), @post.author, title: @post.author.ign) %> +
+ <%= render partial: "users/username", locals: { user: @post.author } %> + <%= link_to "edit", edit_blogpost_path(@post.id), class: "editlink" if mod? %>
- -
- <%= Sanitize.clean(GitHub::Markdown.render_gfm(@post.content), Sanitize::Config::RELAXED).html_safe %> -
-
-

<%= "#{pluralize(@post.comments.length, 'comment')}." %>

- <% @post.comments.each do |c| %> - <%= render "comments/comment", :c => c %> - <% end %> - <%= render "comments/new" %> +
+
+

<%= link_to truncate(@post.title, length: 60, omission: " …"), p %>

+ <%= Sanitize.clean(GitHub::Markdown.render_gfm(@post.content), Sanitize::Config::RELAXED).html_safe %> +
+
+
+

<%= "#{pluralize(@post.comments.length, 'comment')}." %>

+ <% @post.comments.each do |c| %> + <%= render "comments/comment", :c => c %> + <% end %> + <%= render "comments/new" %>
\ No newline at end of file diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb index fa2b9fc..e8eb16e 100644 --- a/app/views/comments/_comment.html.erb +++ b/app/views/comments/_comment.html.erb @@ -1,8 +1,12 @@ -
" id="comment-<%= c.id %>"> - <%= link_user c.author %> <%= c.created_at.strftime("%e. %b %Y, %H:%m") %> - <% if mod? || c.author.is?(current_user) %> - - <% end %> - -
<%= h(c.content).gsub(/(\s*?[\r\n]){3,}/, "\n\n").gsub("\n", "
").html_safe %>
+
+ <%= link_to(image_tag(c.author.avatar_url(64), class: "avatar"), c.author, title: c.author.ign) %> +
"> + <%= render partial: "users/username", locals: { user: c.author } %> + <%= link_to "edit", edit_blogpost_comment_path(c.blogpost, c), class: "editlink" if (mod? || c.author.is?(current_user)) %> +
+
+
+ <%= h(c.content).gsub(/(\s*?[\r\n]){3,}/, "\n\n").gsub("\n", "
").html_safe %> +
+
\ No newline at end of file diff --git a/app/views/forumgroups/edit.html.erb b/app/views/forumgroups/edit.html.erb index 583bf25..85a7132 100644 --- a/app/views/forumgroups/edit.html.erb +++ b/app/views/forumgroups/edit.html.erb @@ -1 +1,24 @@ -

Not yet

\ No newline at end of file +

Edit forum group

+<% role_selection = Role.all_from_to(:normal, :admin).collect{|p|[p.name, p.id]} %> +<%= form_for @group do |f|%> + + + + + + + + + + + + + + + + + +
<%= f.label :name %><%= f.text_field :name, placeholder: "Name" %>
<%= f.label :position %><%= f.number_field :position, placeholder: "Position" %>
<%= f.label :role_read_id, "Min. read role" %><%= f.select :role_read_id, role_selection, include_blank: "None" %>
<%= f.label :role_write_id, "Min. write role" %><%= f.select :role_write_id, role_selection, include_blank: false %>
+ <%= f.submit "Update group", class: "btn blue" %> +<% end %> +<%= button_to "Delete group", @post, :method => "delete", :confirm => "Delete group?\nForums + Threads will not be accessible!", class: "btn red right" %> \ No newline at end of file diff --git a/app/views/forumgroups/new.html.erb b/app/views/forumgroups/new.html.erb index 198db1e..4c8fc27 100644 --- a/app/views/forumgroups/new.html.erb +++ b/app/views/forumgroups/new.html.erb @@ -1,16 +1,23 @@

New forum group

-<%= simple_form_for @group do |f|%> -
- <%= f.label :name %> - <%= f.label :position %> - <%= f.label :role_read_id, "Min read role" %> - <%= f.label :role_write_id, "Min write role" %> -
-
- <%= f.input :name, placeholder: "Name" %> - <%= f.input :position, placeholder: "Position" %> - <%= f.input :role_read_id, as: :select, collection: Role.all_from(Role.get :default), include_blank: "None" %> - <%= f.input :role_write_id, as: :select, collection: Role.all_from(Role.get :default), include_blank: false %> -
- <%= f.submit "Create group", class: "btn blue" %> +<% role_selection = Role.all_from_to(:normal, :admin).collect{|p|[p.name, p.id]} %> +<%= form_for @group do |f|%> + + + + + + + + + + + + + + + + + +
<%= f.label :name %><%= f.text_field :name, placeholder: "Name" %>
<%= f.label :position %><%= f.number_field :position, placeholder: "Position" %>
<%= f.label :role_read_id, "Min. read role" %><%= f.select :role_read_id, role_selection, include_blank: "None" %>
<%= f.label :role_write_id, "Min. write role" %><%= f.select :role_write_id, role_selection, include_blank: false %>
+ <%= f.submit "Create group", class: "btn blue" %> <% end %> \ No newline at end of file diff --git a/app/views/forums/index.html.erb b/app/views/forums/index.html.erb index fb98039..69c5959 100644 --- a/app/views/forums/index.html.erb +++ b/app/views/forums/index.html.erb @@ -1,12 +1,13 @@
<% @groups.each do |group| %> -
+
<%= group.name %> <%= link_to "edit", edit_forumgroup_path(group), class: "editlink" if admin? %> + <%= link_to "+", new_forum_path(forumgroup: group), class: "editlink" if admin? %>
-
+
<% group.forums.each do |f| %> <%= link_to f.name, f, class: "item" %> <% end %> @@ -14,4 +15,10 @@
<% end %> -
\ No newline at end of file +
+ +<% if admin? %> + <%= link_to "New group", new_forumgroup_path, class: "btn blue" %> +<% elsif mod? %> + <%= link_to "New group", nil, class: "btn blue", disabled: true %> +<% end %> \ No newline at end of file diff --git a/app/views/forums/new.html.erb b/app/views/forums/new.html.erb index 4813745..4c962d7 100644 --- a/app/views/forums/new.html.erb +++ b/app/views/forums/new.html.erb @@ -1,17 +1,25 @@ -<%= link_to @group %> → New forum -

New forum

-<%= simple_form_for [@group, @forum] do |f|%> -
- <%= f.label :name %> - <%= f.label :position %> - <%= f.label :role_read_id, "Min read role" %> - <%= f.label :role_write_id, "Min write role" %> -
-
- <%= f.input :name, placeholder: "Name" %> - <%= f.input :position, placeholder: "Position" %> - <%= f.input :role_read_id, as: :select, collection: Role.all_from(Role.get :default), include_blank: "None" %> - <%= f.input :role_write_id, as: :select, collection: Role.all_from(Role.get :default), include_blank: false %> -
- <%= f.submit "Create forum", class: "btn blue" %> -<% end %> +<%= link_to @group, forumgroup_path(@group) %> → New forum +

New forum forum

+<% role_selection = Role.all_from_to(:normal, :admin).collect{|p|[p.name, p.id]} %> +<%= form_for @forum do |f|%> + + + + + + + + + + + + + + + + + +
<%= f.label :name %><%= f.text_field :name, placeholder: "Name" %>
<%= f.label :position %><%= f.number_field :position, placeholder: "Position" %>
<%= f.label :role_read_id, "Min. read role" %><%= f.select :role_read_id, role_selection, include_blank: "None" %>
<%= f.label :role_write_id, "Min. write role" %><%= f.select :role_write_id, role_selection, include_blank: false %>
+ <%= f.hidden_field :forumgroup_id, value: @group.id %> + <%= f.submit "Create forum", class: "btn blue" %> +<% end %> \ No newline at end of file diff --git a/app/views/forums/show.html.erb b/app/views/forums/show.html.erb index c0312e6..ac38a8f 100644 --- a/app/views/forums/show.html.erb +++ b/app/views/forums/show.html.erb @@ -1,14 +1,20 @@ <%= link_to @forum.group, forumgroup_path(@forum.group) %> → <%= link_to @forum %> -

<%= link_to "New thread", new_forum_forumthread_path(@forum), class: "btn blue" %>

- +

<%= @forum %>

-
-
- <%= @forum.name %> <%= link_to "edit", edit_forum_path(@forum), class: "editlink" %> + <% @threads.each do |thread| %> +
+ <%= link_to(image_tag(thread.author.avatar_url(64), class: "avatar"), thread.author, title: thread.author.ign) %> +
+ <%= render partial: "users/username", locals: { user: thread.author } %> + + <%= link_to pluralize(thread.replies.count, "Reply"), thread %> + +
+
+ <%= link_to thread.title, forumthread_path(thread), class: "item#{" locked" if thread.locked}#{" sticky" if thread.sticky}" %> +
-
- <% @threads.each do |thread| %> - <%= link_to thread.title, forum_forumthread_path(@forum, thread), class: "item#{" locked" if thread.locked}#{" sticky" if thread.sticky}" %> - <% end %> -
\ No newline at end of file + <% end %> +
+

<%= link_to "New thread", new_forumthread_path(forum_id: @forum), class: "btn blue" %>

\ No newline at end of file diff --git a/app/views/forumthreads/new.html.erb b/app/views/forumthreads/new.html.erb index 6d1f221..834c782 100644 --- a/app/views/forumthreads/new.html.erb +++ b/app/views/forumthreads/new.html.erb @@ -1,17 +1,22 @@ <%= link_to @forum.group, forumgroup_path(@forum.group) %> → <%= link_to @forum, @forum %> → New thread

New thread

-<%= simple_form_for [@forum, @thread] do |f|%> - <% if mod? %> - <%= f.label :sticky %> <%= f.input :sticky %> - <%= f.label :locked %> <%= f.input :locked %> - <% end %> -
- <%= f.label :title %> -
+<%= form_for [@forum, @thread] do |f|%> + + <% if mod? %> + + + + + + + + + <% end %> +
<%= f.label :sticky %><%= f.check_box :sticky %>
<%= f.label :locked %><%= f.check_box :locked %>
- <%= f.input :title, placeholder: "Title" %> + <%= f.text_field :title, placeholder: "Title" %>
<%= f.hidden_field :content, id: "epic-textarea", placeholder: "Text" %>
- <%= f.submit "Create thread", class: "btn blue" %>
+

<%= f.submit "Create thread", class: "btn blue" %>

<% end %> \ No newline at end of file diff --git a/app/views/forumthreads/show.html.erb b/app/views/forumthreads/show.html.erb index 18bc6d4..d57b2e6 100644 --- a/app/views/forumthreads/show.html.erb +++ b/app/views/forumthreads/show.html.erb @@ -1,16 +1,29 @@ <%= link_to @thread.forum.group, forumgroup_path(@thread.forum.group) %> → <%= link_to @thread.forum, @thread.forum %> → <%= link_to @thread %> -
-
-

<%= @thread.title %>

+
+ <%= params.inspect %>
+ <%= @forum.inspect %>
+ <%= @thread.forum.inspect %> +
+
+ <%= link_to(image_tag(@thread.author.avatar_url(64), class: "avatar"), @thread.author, title: @thread.author.ign) %> +
+ <%= render partial: "users/username", locals: { user: @thread.author } %> + <%= link_to "edit", edit_forumthread_path( @thread), class: "editlink" if mod? %>
-
<%= link_user @thread.author %> on <%= @thread.created_at.strftime("%e. %b %Y") %> - <% if mod? %> - <%= link_to "edit", edit_forum_forumthread_path(@thread.forum, @thread), class: "thread-edit" %> - <% end %> -
-
- <%= Sanitize.clean(GitHub::Markdown.render_gfm(@thread.content), Sanitize::Config::RELAXED).html_safe %> +
+
+

<%= link_to truncate(@thread.title, length: 60, omission: " …"), p %>

+ <%= Sanitize.clean(GitHub::Markdown.render_gfm(@thread.content), Sanitize::Config::RELAXED).html_safe %> +
-
-(replies go here) \ No newline at end of file +
+

<%= "#{pluralize(@thread.replies.length, 'reply')}." %>

+ <% @thread.replies.each do |c| %> + Reply<%# render "threadreplies/reply", :c => c %> + <% end %> + <% unless @thread.can_read?(current_user) %> + new + <%# render "threadreplies/new" %> + <% end %> +
\ No newline at end of file diff --git a/app/views/layouts/_head.html.erb b/app/views/layouts/_head.html.erb index f3de1f0..47cac44 100644 --- a/app/views/layouts/_head.html.erb +++ b/app/views/layouts/_head.html.erb @@ -5,10 +5,10 @@
> <% if current_user %> - <%= link_to current_user.name.truncate(14), current_user %>
+ <%= link_to current_user.name, current_user %>
<%= link_to "Logout", logout_path %>
- <%= link_to image_tag(avatar_url(current_user.id, 32), :class => "avatar"), current_user %> + <%= link_to image_tag(current_user.avatar_url(32), :class => "avatar"), current_user %> <% else %> <%= link_to "Log in", login_path(return_path: request.env['PATH_INFO']), action: "new" %> | <%= link_to "Sign up", signup_path %> <% end %> diff --git a/app/views/redstoner_mailer/register_mail.html.erb b/app/views/redstoner_mailer/register_mail.html.erb index 382fa17..ce02398 100644 --- a/app/views/redstoner_mailer/register_mail.html.erb +++ b/app/views/redstoner_mailer/register_mail.html.erb @@ -1,7 +1,7 @@ Hi <%= @user.name %>!

Thank you for registering on Redstoner.com!

-

To use your account, you need to <%= link_to "confirm", confirm_user_path(@user, code: @user.confirm_code, only_path: false) %> your email address. +

To use your account, you need to <%= link_to "confirm", confirm_user_path(@user, code: @user.email_token, only_path: false) %> your email address.

<% if @mcpw %>
@@ -21,9 +21,12 @@ Hi <%= @user.name %>!

Please click this link to confirm your registration:

- <%= link_to "confirm my email", confirm_user_path(@user, code: @user.confirm_code, only_path: false), style: "text-decoration: none; color: #f2f2f2; padding: 0.5em 2em; background-color: #4096EE; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; display: inline-block; text-transform: uppercase;" %> + <%= link_to "confirm my email", confirm_user_path(@user, code: @user.email_token, only_path: false), style: "text-decoration: none; color: #f2f2f2; padding: 0.5em 2em; background-color: #4096EE; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; display: inline-block; text-transform: uppercase;" %>

If you have any questions or problems, just ask one of our <%= link_to "Staff", users_path(role: "staff", only_path: false) %> in-game.

-

Your Redstoner team

\ No newline at end of file +

Your Redstoner team

+ + +If you did not sign up on redstoner.com you can safely ignore this email \ No newline at end of file diff --git a/app/views/users/_username.html.erb b/app/views/users/_username.html.erb new file mode 100644 index 0000000..21e06ee --- /dev/null +++ b/app/views/users/_username.html.erb @@ -0,0 +1,4 @@ +
+ <%= link_to user.name, user_path(user.id), class: "role #{user.role.name}", title: user.ign %> + <% link_to_if "$", donate_statics_path, class: "donor", title: "Donator" if user.donor? %> +
\ No newline at end of file diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index e03bd64..bb13e54 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -7,68 +7,67 @@ - <%= image_tag avatar_url(@user.id, 128), :class => "user-avatar avatar", :alt => "avatar" %> + <%= image_tag @user.avatar_url(128), :class => "user-avatar avatar", :alt => "avatar" %> Display name - <%= f.input :name, :label => false, disabled: !can_edit? %> - - - In-game name - - <%= f.input :ign, :label => false, disabled: !(mod? && current_user.role >= @user.role) %> - - - - Role - - <% if mod? && current_user.role >= @user.role %> - <%= f.association :role, :label => false, :collection => Role.all_until(current_user.role), :include_blank => false %> - <% else %> - <%= f.input :role, label: false, disabled: true %> - <% end %> - - - - - - Skype username - - - <%= f.input :skype, label: false, placeholder: "Skype username", disabled: !can_edit? %> - - - - - Show Skype to - - - <%= f.input :skype_public, label: false, as: :select, collection: [["Staff only", false], ["All users", true]], include_blank: false, input_html: { disabled: !can_edit? } %> - - - YouTube username - - <%= f.input :youtube, :label => false, placeholder: "YouTube username", disabled: !can_edit? %> - - - - Twitter username - - <%= f.input :twitter, :label => false, placeholder: "Twitter username", disabled: !(@user.is?(current_user) && confirmed? || (mod? && current_user.role >= @user.role)) %> - - - - About you - - <%= f.input :about, :label => false, :input_html => {:class => "vertical"}, placeholder: "Tell us something about you...", disabled: !can_edit? %> - - - - - <%= f.submit "Save profile", class: "btn blue", disabled: (@user.unconfirmed? && @user.is?(current_user)) %> - <% if @user.unconfirmed? %> - <% if @user.is?(current_user) %> + <%= f.input :name, :label => false, disabled: !can_edit? %> + + + <% if mod? %> + + In-game name + + <%= f.input :ign, :label => false, disabled: !(mod? && current_user.role >= @user.role) %> + + + + Role + + <% if mod? && current_user.role >= @user.role %> + <%= f.association :role, :label => false, :collection => Role.all_to(current_user.role), :include_blank => false %> + <% else %> + <%= f.input :role, label: false, disabled: true %> + <% end %> + + + <% end %> + + Skype username + + <%= f.input :skype, label: false, placeholder: "Skype username", disabled: !can_edit? %> + + + + Show Skype to + + <%= f.input :skype_public, label: false, as: :select, collection: [["Staff only", false], ["All users", true]], include_blank: false, input_html: { disabled: !can_edit? } %> + + + + YouTube username + + <%= f.input :youtube, :label => false, placeholder: "YouTube username", disabled: !can_edit? %> + + + + Twitter username + + <%= f.input :twitter, :label => false, placeholder: "Twitter username", disabled: !(@user.is?(current_user) && confirmed? || (mod? && current_user.role >= @user.role)) %> + + + + About you + + <%= f.input :about, :label => false, :input_html => {:class => "vertical"}, placeholder: "Tell us something about you...", disabled: !can_edit? %> + + + + +<%= f.submit "Save profile", class: "btn blue", disabled: (!@user.confirmed? && @user.is?(current_user)) %> +<% if !@user.confirmed? %> + <% if @user.is?(current_user) %> Please confirm your email adress first! <% else %> This user has not confirmed his email! diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index b9f45f6..ec662b4 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,6 +1,5 @@ -<% filter = params[:role] %> -<% if filter %> -

All '<%= filter %>' users

+<% if params[:role] %> +

All '<%= params[:role] %>' users

<%= link_to "show all", users_path %> <% else %>

All users

@@ -8,13 +7,10 @@
<% @users.each do |u| %>
- <%= link_to u, class: "avatar_url" do %> - <%= image_tag(avatar_url(u.id, 64), :class => "avatar", :alt => "avatar") %> - <% end %> - <% end %> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 9d5b240..bf7ec55 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,19 +1,29 @@

Sign up

-<%= simple_form_for @user do |f| %> -
- <%= f.label :name, "Display name" %> - <%= f.label :ign, "Minecraft name" %> - <%= f.label :email, "Email" %> - <%= f.label :password, "Password" %> - <%= f.label :password_confirmation, "Confirm" %> -
-
- <%= f.input :name, placeholder: "John" %> - <%= f.input :ign, placeholder: "johndoe_1337" %> - <%= f.input :email, placeholder: "johndoe@example.com" %> - <%= f.input :password, placeholder: "••••••" %> - <%= f.input :password_confirmation, placeholder: "••••••" %> -
+

To get a token, join the Minecraft server (redstoner.com) and use the /token <your-email> command.

+ +<%= form_for @user do |f| %> + + + + + + + + + + + + + + + + + + + + + +
<%= f.label :ign, "Minecraft name" %><%= f.text_field :ign, placeholder: "Steve", pattern: "[a-zA-Z0-9_]{2,16}", required: true, title: "Your IGN" %>
<%= f.label :email, "Email" %><%= f.email_field :email, placeholder: "steve@example.com", required: true, pattern: ".+@.+", title: "enter valid email adress", "x-moz-errormessage" => "enter valid email adress" %>
<%= f.label :registration_token, "Token" %><%= text_field_tag :registration_token, nil, placeholder: "abcdef", required: true, pattern: "[a-z]{6}", title: "6 character token", "x-moz-errormessage" => "6 character token" %>
<%= f.label :password, "Password" %><%= f.password_field :password, placeholder: "secret", required: true, pattern: ".{8,}", title: "minimum 8 characters", "x-moz-errormessage" => "minimum 8 characters" %>
<%= f.label :password_confirmation, "Confirm" %><%= f.password_field :password_confirmation, placeholder: "secret", required: true, pattern: ".{8,}", title: "minimum 8 characters", "x-moz-errormessage" => "minimum 8 characters" %>
<%= f.submit "Sign up", class: "btn blue" %> <% end %> \ No newline at end of file diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index a8d6336..5985c33 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -15,7 +15,7 @@ <% if @user.banned? %> This user is banned! <% end %> - <% if @user.unconfirmed? %> + <% if !@user.confirmed? %> <% if @user.is?(current_user) %> Please confirm your email <%= @user.email %> ! <% else %> @@ -25,62 +25,62 @@ <% if @user.is?(current_user) %> Your account has been disabled. <% else %> - This user is disabled or does no longer exist. + This account has been disabled. <% end %> <% end %> -<%= image_tag avatar_url(@user.id, 128), :class => "user-avatar avatar", :alt => "avatar" %> + <%= image_tag @user.avatar_url(128), :class => "user-avatar avatar", :alt => "avatar" %> - - - - - - - - - <% if current_user && !@user.skype.blank? && (@user.skype_public || current_user == @user || mod?) %> - - - - - <% end %> - <% if !@user.youtube.blank? && !@user.youtube_channelname.blank? %> - - - - - <% end %> - <% if !@user.twitter.blank? %> - - - - - <% end %> - - - - - <% if mod? || current_user == @user %> - <% if mod? %> + + + + + + + + + <% if current_user && !@user.skype.blank? && (@user.skype_public || current_user == @user || mod?) %> + + + + + <% end %> + <% if !@user.youtube.blank? && !@user.youtube_channelname.blank? %> + + + + + <% end %> + <% if !@user.twitter.blank? %> + + + + + <% end %> + + + + + <% if mod? || current_user == @user %> + <% if mod? %> - <% end %> - - - - - - - - - <% end %> - -
IGN<%= @user.ign %>
Role<%= link_to @user.role, users_path(:role => @user.role.name) %>
Skype<%= link_to @user.skype, "skype:#{@user.skype}?chat", target: "_blank" %>
YouTube<%= link_to @user.youtube_channelname, "https://youtube.com/user/#{CGI.escape(@user.youtube)}", :target => "_blank" %>
Twitter<%= link_to "@#{@user.twitter}", "https://twitter.com/#{CGI.escape(@user.twitter)}", :target => "_blank" %>
Joined<%= @user.created_at.strftime("%e. %b %Y") %>
IGN<%= @user.ign %>
Role<%= link_to @user.role, users_path(:role => @user.role.name) %>
Skype<%= link_to @user.skype, "skype:#{@user.skype}?chat", target: "_blank" %>
YouTube<%= link_to @user.youtube_channelname, "https://youtube.com/user/#{CGI.escape(@user.youtube)}", :target => "_blank" %>
Twitter<%= link_to "@#{@user.twitter}", "https://twitter.com/#{CGI.escape(@user.twitter)}", :target => "_blank" %>
Joined<%= @user.created_at.strftime("%e. %b %Y, %H:%m") %>
Last IP <%= @user.last_ip %>
Email<%= mail_to @user.email, @user.email, :subject => "Redstoner" %>
Last login<%= @user.last_login.strftime("%e. %b %Y, %H:%M") %>
-
- <%= @user.about.blank? ? "nothing".html_safe : @user.about %> + <% end %> + + Email + <%= mail_to @user.email, @user.email, :subject => "Redstoner" %> + + + Last seen + <%= @user.last_seen.strftime("%e. %b %Y, %H:%M") %> + + <% end %> + + +
+ <%= @user.about.blank? ? "nothing".html_safe : @user.about %>
\ No newline at end of file diff --git a/config/initializers/form_errors.rb b/config/initializers/form_errors.rb new file mode 100644 index 0000000..b9b9416 --- /dev/null +++ b/config/initializers/form_errors.rb @@ -0,0 +1,8 @@ +ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| + if html_tag =~ /\