Added adminpanel to this repo
							
								
								
									
										221
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @@ -98,6 +98,14 @@ | ||||
|       "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", | ||||
|       "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" | ||||
|     }, | ||||
|     "assert": { | ||||
|       "version": "1.4.1", | ||||
|       "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", | ||||
|       "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", | ||||
|       "requires": { | ||||
|         "util": "0.10.3" | ||||
|       } | ||||
|     }, | ||||
|     "assert-plus": { | ||||
|       "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", | ||||
|       "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" | ||||
| @@ -145,6 +153,11 @@ | ||||
|       "version": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", | ||||
|       "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" | ||||
|     }, | ||||
|     "bcrypt-nodejs": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", | ||||
|       "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" | ||||
|     }, | ||||
|     "bcrypt-pbkdf": { | ||||
|       "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", | ||||
|       "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", | ||||
| @@ -173,6 +186,11 @@ | ||||
|       "version": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", | ||||
|       "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=" | ||||
|     }, | ||||
|     "bluebird": { | ||||
|       "version": "3.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", | ||||
|       "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" | ||||
|     }, | ||||
|     "bmp-js": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.0.3.tgz", | ||||
| @@ -362,10 +380,24 @@ | ||||
|       "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | ||||
|       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" | ||||
|     }, | ||||
|     "cookies": { | ||||
|       "version": "0.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", | ||||
|       "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=", | ||||
|       "requires": { | ||||
|         "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", | ||||
|         "keygrip": "1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "core-util-is": { | ||||
|       "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", | ||||
|       "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" | ||||
|     }, | ||||
|     "crc": { | ||||
|       "version": "3.4.4", | ||||
|       "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", | ||||
|       "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" | ||||
|     }, | ||||
|     "cryptiles": { | ||||
|       "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", | ||||
|       "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", | ||||
| @@ -662,6 +694,22 @@ | ||||
|       "resolved": "https://registry.npmjs.org/express-recaptcha/-/express-recaptcha-3.0.1.tgz", | ||||
|       "integrity": "sha1-b/a25u1D5u94ZD9W46qP/igDlMg=" | ||||
|     }, | ||||
|     "express-session": { | ||||
|       "version": "1.15.6", | ||||
|       "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", | ||||
|       "integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==", | ||||
|       "requires": { | ||||
|         "cookie": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", | ||||
|         "cookie-signature": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | ||||
|         "crc": "3.4.4", | ||||
|         "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||||
|         "depd": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", | ||||
|         "on-headers": "1.0.1", | ||||
|         "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", | ||||
|         "uid-safe": "2.1.5", | ||||
|         "utils-merge": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "express-subdomain": { | ||||
|       "version": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", | ||||
|       "integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s=" | ||||
| @@ -1412,6 +1460,16 @@ | ||||
|         "verror": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "kareem": { | ||||
|       "version": "2.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.0.3.tgz", | ||||
|       "integrity": "sha512-WloXk3nyByx9FEB5WY7WFEXIZB/QA+zy7c2kJMjnZCebjepEyQcJzazgLiKcTS/ltZeEoeEQ1A1pau1fEDlnIA==" | ||||
|     }, | ||||
|     "keygrip": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", | ||||
|       "integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E=" | ||||
|     }, | ||||
|     "kind-of": { | ||||
|       "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", | ||||
|       "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", | ||||
| @@ -1499,6 +1557,11 @@ | ||||
|         "lodash._root": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "lodash.get": { | ||||
|       "version": "4.4.2", | ||||
|       "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", | ||||
|       "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" | ||||
|     }, | ||||
|     "lodash.isarguments": { | ||||
|       "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", | ||||
|       "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" | ||||
| @@ -1740,6 +1803,89 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "mongoose": { | ||||
|       "version": "5.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.0.3.tgz", | ||||
|       "integrity": "sha512-y4NlLzZaQe5vJHjcEjHLKK6utjs7sVEPN971+d1vVJJGrmA+zeeFA1MEmC1J0ujD34eOSghnExXJPwCrxHHZCw==", | ||||
|       "requires": { | ||||
|         "async": "2.1.4", | ||||
|         "bson": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", | ||||
|         "kareem": "2.0.3", | ||||
|         "lodash.get": "4.4.2", | ||||
|         "mongodb": "3.0.2", | ||||
|         "mongoose-legacy-pluralize": "1.0.2", | ||||
|         "mpath": "0.3.0", | ||||
|         "mquery": "3.0.0", | ||||
|         "ms": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|         "regexp-clone": "0.0.1", | ||||
|         "sliced": "1.0.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "async": { | ||||
|           "version": "2.1.4", | ||||
|           "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", | ||||
|           "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", | ||||
|           "requires": { | ||||
|             "lodash": "4.17.5" | ||||
|           } | ||||
|         }, | ||||
|         "lodash": { | ||||
|           "version": "4.17.5", | ||||
|           "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", | ||||
|           "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" | ||||
|         }, | ||||
|         "mongodb": { | ||||
|           "version": "3.0.2", | ||||
|           "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.0.2.tgz", | ||||
|           "integrity": "sha512-E50FmpSQchZAimn2uPIegoNoH9UQYR1yiGHtQPmmg8/Ekc97w6owHoqaBoz+assnd9V5LxMzmQ/VEWMsQMgZhQ==", | ||||
|           "requires": { | ||||
|             "mongodb-core": "3.0.2" | ||||
|           } | ||||
|         }, | ||||
|         "mongodb-core": { | ||||
|           "version": "3.0.2", | ||||
|           "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.0.2.tgz", | ||||
|           "integrity": "sha512-p1B0qwFQUw6C1OlFJnrOJp8KaX7MuGoogRbTaupRt0y+pPRkMllHWtE9V6i1CDtTvI3/3sy2sQwqWez7zuXEAA==", | ||||
|           "requires": { | ||||
|             "bson": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", | ||||
|             "require_optional": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "mongoose-legacy-pluralize": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", | ||||
|       "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" | ||||
|     }, | ||||
|     "mpath": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", | ||||
|       "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" | ||||
|     }, | ||||
|     "mpromise": { | ||||
|       "version": "0.5.5", | ||||
|       "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", | ||||
|       "integrity": "sha1-9bJCWddjrMIlewoMjG2Gb9UXMuY=" | ||||
|     }, | ||||
|     "mquery": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.0.0.tgz", | ||||
|       "integrity": "sha512-WL1Lk8v4l8VFSSwN3yCzY9TXw+fKVYKn6f+w86TRzOLSE8k1yTgGaLBPUByJQi8VcLbOdnUneFV/y3Kv874pnQ==", | ||||
|       "requires": { | ||||
|         "bluebird": "3.5.0", | ||||
|         "debug": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||||
|         "regexp-clone": "0.0.1", | ||||
|         "sliced": "0.0.5" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "sliced": { | ||||
|           "version": "0.0.5", | ||||
|           "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", | ||||
|           "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "ms": { | ||||
|       "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||||
| @@ -1855,6 +2001,11 @@ | ||||
|         "ee-first": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "on-headers": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", | ||||
|       "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" | ||||
|     }, | ||||
|     "once": { | ||||
|       "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", | ||||
|       "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", | ||||
| @@ -1966,6 +2117,28 @@ | ||||
|       "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", | ||||
|       "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" | ||||
|     }, | ||||
|     "passport": { | ||||
|       "version": "0.4.0", | ||||
|       "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", | ||||
|       "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", | ||||
|       "requires": { | ||||
|         "passport-strategy": "1.0.0", | ||||
|         "pause": "0.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "passport-local": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", | ||||
|       "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", | ||||
|       "requires": { | ||||
|         "passport-strategy": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "passport-strategy": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", | ||||
|       "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" | ||||
|     }, | ||||
|     "path-is-absolute": { | ||||
|       "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", | ||||
|       "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" | ||||
| @@ -1989,6 +2162,11 @@ | ||||
|       "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||||
|       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" | ||||
|     }, | ||||
|     "pause": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", | ||||
|       "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" | ||||
|     }, | ||||
|     "performance-now": { | ||||
|       "version": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", | ||||
|       "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" | ||||
| @@ -2046,6 +2224,11 @@ | ||||
|       "version": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", | ||||
|       "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=" | ||||
|     }, | ||||
|     "random-bytes": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", | ||||
|       "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" | ||||
|     }, | ||||
|     "randomatic": { | ||||
|       "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", | ||||
|       "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", | ||||
| @@ -2142,6 +2325,11 @@ | ||||
|         "is-equal-shallow": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "regexp-clone": { | ||||
|       "version": "0.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", | ||||
|       "integrity": "sha1-p8LgmJH9vzj7sQ03b7cwA+aKxYk=" | ||||
|     }, | ||||
|     "remove-trailing-separator": { | ||||
|       "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", | ||||
|       "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" | ||||
| @@ -2280,6 +2468,11 @@ | ||||
|       "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", | ||||
|       "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" | ||||
|     }, | ||||
|     "sliced": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", | ||||
|       "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" | ||||
|     }, | ||||
|     "sntp": { | ||||
|       "version": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz", | ||||
|       "integrity": "sha1-UGQRDwr4X3z9t9a2ekACjOUrSys=", | ||||
| @@ -2547,6 +2740,14 @@ | ||||
|       "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "uid-safe": { | ||||
|       "version": "2.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", | ||||
|       "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", | ||||
|       "requires": { | ||||
|         "random-bytes": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "uid2": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", | ||||
| @@ -2587,6 +2788,21 @@ | ||||
|       "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", | ||||
|       "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" | ||||
|     }, | ||||
|     "util": { | ||||
|       "version": "0.10.3", | ||||
|       "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", | ||||
|       "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", | ||||
|       "requires": { | ||||
|         "inherits": "2.0.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "inherits": { | ||||
|           "version": "2.0.1", | ||||
|           "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", | ||||
|           "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "util-deprecate": { | ||||
|       "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", | ||||
|       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" | ||||
| @@ -2624,6 +2840,11 @@ | ||||
|         "extsprintf": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" | ||||
|       } | ||||
|     }, | ||||
|     "vhost": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/vhost/-/vhost-3.0.2.tgz", | ||||
|       "integrity": "sha1-L7HezUxGaqiLD5NBrzPcGv8keNU=" | ||||
|     }, | ||||
|     "vinyl": { | ||||
|       "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", | ||||
|       "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", | ||||
|   | ||||
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -27,14 +27,18 @@ | ||||
|   }, | ||||
|   "homepage": "https://github.com/zoff-music/zoff#readme", | ||||
|   "dependencies": { | ||||
|     "assert": "^1.4.1", | ||||
|     "bad-words": "^1.5.1", | ||||
|     "bcrypt-nodejs": "0.0.3", | ||||
|     "body-parser": "^1.17.1", | ||||
|     "color-thief-jimp": "^2.0.2", | ||||
|     "cookie-parser": "^1.4.3", | ||||
|     "cookies": "^0.7.1", | ||||
|     "emoji-strip": "^0.0.3", | ||||
|     "express": "^4.15.2", | ||||
|     "express-handlebars": "^3.0.0", | ||||
|     "express-recaptcha": "^3.0.1", | ||||
|     "express-session": "^1.15.6", | ||||
|     "express-subdomain": "^1.0.5", | ||||
|     "gulp": "^3.9.1", | ||||
|     "gulp-concat": "^2.6.1", | ||||
| @@ -44,13 +48,18 @@ | ||||
|     "mobile-detect": "^1.3.7", | ||||
|     "mongodb": "^2.0.27", | ||||
|     "mongojs": "^2.4.0", | ||||
|     "mongoose": "^5.0.3", | ||||
|     "mpromise": "^0.5.5", | ||||
|     "node-cryptojs-aes": "^0.4.0", | ||||
|     "nodemailer": "^4.0.1", | ||||
|     "passport": "^0.4.0", | ||||
|     "passport-local": "^1.0.0", | ||||
|     "redis": "^2.8.0", | ||||
|     "request": "^2.72.0", | ||||
|     "socket.io": "^2.0.3", | ||||
|     "socket.io-redis": "^5.2.0", | ||||
|     "sticky-session": "^1.1.2", | ||||
|     "uniqid": "^4.1.1" | ||||
|     "uniqid": "^4.1.1", | ||||
|     "vhost": "^3.0.2" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										215
									
								
								server/admin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,215 @@ | ||||
| var express = require('express'); | ||||
| var app = express(); | ||||
|  | ||||
| const path = require('path'); | ||||
| const publicPath = path.join(__dirname, 'public'); | ||||
| var exphbs = require('express-handlebars'); | ||||
| var hbs = exphbs.create({ | ||||
|    defaultLayout: publicPath + '/layouts/admin/main', | ||||
|    layoutsDir: publicPath + '/layouts', | ||||
|    partialsDir: publicPath + '/partials' | ||||
| }); | ||||
|  | ||||
| var passport = require('passport'); | ||||
| var mpromise = require('mpromise'); | ||||
| var LocalStrategy = require('passport-local').Strategy; | ||||
| var mongoose = require('mongoose'); | ||||
| var mongo_db_cred = require(path.join(__dirname, './config/mongo_config.js')); | ||||
| var mongojs = require('mongojs'); | ||||
| var db = mongojs(mongo_db_cred.config); | ||||
| var token_db = mongojs("tokens"); | ||||
| var bodyParser = require('body-parser'); | ||||
| var Cookies = require('cookies'); | ||||
| var session = require('express-session'); | ||||
| var api = require('./routing/admin/api.js'); | ||||
|  | ||||
| var User = require('./models/user.js'); | ||||
| var url = 'mongodb://localhost/users'; | ||||
| mongoose.connect(url); | ||||
|  | ||||
|  | ||||
| app.engine('handlebars', hbs.engine); | ||||
| app.set('view engine', 'handlebars'); | ||||
| app.enable('view cache'); | ||||
| app.set('views', publicPath); | ||||
| app.use(bodyParser.urlencoded({ | ||||
|   extended: true | ||||
| })); | ||||
| app.use(session({ | ||||
|   secret: mongo_db_cred.secret, | ||||
|   resave: true, | ||||
|   saveUninitialized: true | ||||
| })); // session secret | ||||
| app.use(passport.initialize()); | ||||
| app.use(passport.session()); // persistent login sessions | ||||
|  | ||||
| //app.use('/assets', express.static(publicPath + '/assets')); | ||||
|  | ||||
| passport.serializeUser(function(user, done) { | ||||
|    done(null, user.id); | ||||
| }); | ||||
|  | ||||
|  | ||||
|  | ||||
| // used to deserialize the user | ||||
| passport.deserializeUser(function(id, done) { | ||||
|    User.findById(id, function(err, user) { | ||||
|       done(err, user); | ||||
|    }); | ||||
| }); | ||||
|  | ||||
| passport.use('local-signup', new LocalStrategy({ | ||||
|    // by default, local strategy uses username and password, we will override with username | ||||
|    usernameField : 'username', | ||||
|    passwordField : 'password', | ||||
|    passReqToCallback : true // allows us to pass back the entire request to the callback | ||||
| }, | ||||
| function(req, username, password, done) { | ||||
|    // asynchronous | ||||
|    // User.findOne wont fire unless data is sent back | ||||
|    process.nextTick(function() { | ||||
|  | ||||
|       // find a user whose username is the same as the forms username | ||||
|       // we are checking to see if the user trying to login already exists | ||||
|       var token = req.param("token"); | ||||
|       token_db.collection("tokens").find({token: token}, function(err, docs){ | ||||
|          if(docs.length == 1){ | ||||
|             token_db.collection("tokens").remove({token: token}, function(err, docs){ | ||||
|                User.findOne({ 'username' :  username }, function(err, user) { | ||||
|                   // if there are any errors, return the error | ||||
|                   if (err) | ||||
|                   return done(err); | ||||
|  | ||||
|                   // check to see if theres already a user with that username | ||||
|                   if (user) { | ||||
|                      return done(null, false); | ||||
|                   } else { | ||||
|  | ||||
|                      // if there is no user with that username | ||||
|                      // create the user | ||||
|                      var newUser            = new User(); | ||||
|  | ||||
|                      // set the user's local credentials | ||||
|                      newUser.username    = username; | ||||
|                      newUser.password = newUser.generateHash(password); | ||||
|  | ||||
|                      // save the user | ||||
|                      newUser.save(function(err) { | ||||
|                         if (err) | ||||
|                         throw err; | ||||
|                         return done(null, newUser); | ||||
|                      }); | ||||
|                   } | ||||
|  | ||||
|                }); | ||||
|             }); | ||||
|          } else { | ||||
|             return done(null, false); | ||||
|          } | ||||
|       }); | ||||
|    }); | ||||
|  | ||||
| })); | ||||
|  | ||||
| passport.use('local-login', new LocalStrategy({ | ||||
|    // by default, local strategy uses username and password, we will override with email | ||||
|    usernameField : 'username', | ||||
|    passwordField : 'password', | ||||
|    passReqToCallback : true // allows us to pass back the entire request to the callback | ||||
| },    function(req, username, password, done) { // callback with email and password from our form | ||||
|  | ||||
|    // find a user whose email is the same as the forms email | ||||
|    // we are checking to see if the user trying to login already exists | ||||
|    User.findOne({ 'username' :  username }, function(err, user) { | ||||
|       // if there are any errors, return the error before anything else | ||||
|       if (err) | ||||
|       return done(err); | ||||
|  | ||||
|       // if no user is found, return the message | ||||
|       if (!user) | ||||
|       return done(null, false); // req.flash is the way to set flashdata using connect-flash | ||||
|  | ||||
|       // if the user is found but the password is wrong | ||||
|       if (!user.validPassword(password)) | ||||
|       return done(null, false); // create the loginMessage and save it to session as flashdata | ||||
|  | ||||
|       // all is well, return successful user | ||||
|  | ||||
|       return done(null, user); | ||||
|    }); | ||||
|  | ||||
| })); | ||||
|  | ||||
| app.post('/signup', passport.authenticate('local-signup', { | ||||
|    successRedirect : '/', // redirect to the secure profile section | ||||
|    failureRedirect : '/signup', // redirect back to the signup page if there is an error | ||||
|    failureFlash : true // allow flash messages | ||||
| })); | ||||
|  | ||||
| app.post('/login', passport.authenticate('local-login', { | ||||
|    successRedirect : '/', // redirect to the secure profile section | ||||
|    failureRedirect : '/login', // redirect back to the signup page if there is an error | ||||
|    failureFlash : true // allow flash messages | ||||
| })); | ||||
|  | ||||
| app.use('/login', isLoggedInTryingToLogIn, function(req, res) { | ||||
|    var data = { | ||||
|       where_get: "not_authenticated" | ||||
|    }; | ||||
|  | ||||
|    res.render('layouts/admin/not_authenticated', data); | ||||
| }); | ||||
|  | ||||
| app.use('/signup', isLoggedInTryingToLogIn, function(req, res) { | ||||
|    var data = { | ||||
|       where_get: "not_authenticated" | ||||
|    }; | ||||
|  | ||||
|    res.render('layouts/admin/not_authenticated', data); | ||||
| }); | ||||
|  | ||||
| app.use('/', api); | ||||
|  | ||||
| app.use('/logout', function(req, res) { | ||||
|    req.logout(); | ||||
|    res.redirect('/login'); | ||||
| }); | ||||
|  | ||||
| app.use('/assets', express.static(publicPath + '/assets')); | ||||
|  | ||||
| app.use('/', isLoggedIn, function(req, res) { | ||||
|    var data = { | ||||
|       where_get: "authenticated", | ||||
|       year: new Date().getYear()+1900, | ||||
|    }; | ||||
|  | ||||
|    res.render('layouts/admin/authenticated', data); | ||||
| }); | ||||
|  | ||||
| function makeid() | ||||
| { | ||||
|    var text = ""; | ||||
|    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||||
|  | ||||
|    for( var i=0; i < 20; i++ ) | ||||
|    text += possible.charAt(Math.floor(Math.random() * possible.length)); | ||||
|  | ||||
|    return text; | ||||
| } | ||||
|  | ||||
| function isLoggedInTryingToLogIn(req, res, next){ | ||||
|    if(!req.isAuthenticated()){ | ||||
|       return next(); | ||||
|    } | ||||
|    res.redirect("/"); | ||||
| } | ||||
|  | ||||
| function isLoggedIn(req, res, next) { | ||||
|    if (req.isAuthenticated()) | ||||
|    return next(); | ||||
|    res.redirect('/login'); | ||||
| } | ||||
|  | ||||
| //app.listen(default_port); | ||||
|  | ||||
| module.exports = app; | ||||
| @@ -4,19 +4,23 @@ var cluster = require('cluster'), | ||||
|     publicPath = path.join(__dirname, 'public'), | ||||
|     http = require('http'), | ||||
|     port = 8080, | ||||
|     num_processes = require('os').cpus().length; | ||||
|     num_processes = require('os').cpus().length, | ||||
|     express = require('express'), | ||||
|     vhost = require('vhost'), | ||||
|     app = express(); | ||||
|  | ||||
| try { | ||||
|     a | ||||
|     var redis = require("redis"); | ||||
|     var client = redis.createClient({host: "localhost", port: 6379}); | ||||
|     client.quit(); | ||||
|     startClustered(); | ||||
|     startClustered(true); | ||||
| } catch(e) { | ||||
|     console.log("Couldn't connect to redis-server, assuming non-clustered run"); | ||||
|     startSingle(false); | ||||
|     startClustered(false); | ||||
| } | ||||
|  | ||||
| function startClustered() { | ||||
| function startClustered(redis_enabled) { | ||||
|     //Found https://stackoverflow.com/questions/40885592/use-node-js-cluster-with-socket-io-chat-application | ||||
|     if (cluster.isMaster) { | ||||
|         var workers = []; | ||||
| @@ -47,12 +51,13 @@ function startClustered() { | ||||
|             worker.send('sticky-session:connection', connection); | ||||
|         }).listen(port); | ||||
|     } else { | ||||
|         startSingle(true); | ||||
|         startSingle(true, redis_enabled); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function startSingle(clustered) { | ||||
|     var app = require('./index.js'); | ||||
| function startSingle(clustered, redis_enabled) { | ||||
|     var client = require('./client.js'); | ||||
|     var admin = require('./admin.js'); | ||||
|     try { | ||||
|         var cert_config = require(path.join(path.join(__dirname, 'config'), 'cert_config.js')); | ||||
|         var fs = require('fs'); | ||||
| @@ -66,24 +71,47 @@ function startSingle(clustered) { | ||||
|         }; | ||||
|  | ||||
|         var https = require('https'); | ||||
|         server = https.Server(credentials, app); | ||||
|         server = https.Server(credentials, client); | ||||
|  | ||||
|     } catch(err){ | ||||
|         console.log("Starting without https (probably on localhost)"); | ||||
|         var http = require('http'); | ||||
|         server = http.Server(app); | ||||
|         server = http.Server(client); | ||||
|         //add = ",http://localhost:80*,http://localhost:8080*,localhost:8080*, localhost:8082*,http://zoff.dev:80*,http://zoff.dev:8080*,zoff.dev:8080*, zoff.dev:8082*"; | ||||
|     } | ||||
|  | ||||
|     admin_server = http.Server(admin); | ||||
|  | ||||
|     if(clustered) { | ||||
|         server.listen(onListen); | ||||
|         app | ||||
|         .use( vhost('*', function(req, res) { | ||||
|             server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .use( vhost('remote.*', function(req, res) { | ||||
|             server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .use( vhost('admin.*', function(req, res) { | ||||
|             admin_server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .listen(onListen); | ||||
|         //server.listen(onListen); | ||||
|     } else { | ||||
|         server.listen(port, onListen); | ||||
|         app | ||||
|         .use( vhost('*', function(req, res) { | ||||
|             server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .use( vhost('remote.*', function(req, res) { | ||||
|             server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .use( vhost('admin.*', function(req, res) { | ||||
|             admin_server.emit("request", req, res); | ||||
|         }) ) | ||||
|         .listen(port, onListen); | ||||
|         //server.listen(port, onListen); | ||||
|     } | ||||
|  | ||||
|     var socketIO = app.socketIO; | ||||
|     var socketIO = client.socketIO; | ||||
|  | ||||
|     if(clustered) { | ||||
|     if(redis_enabled) { | ||||
|         var redis = require('socket.io-redis'); | ||||
|         try { | ||||
|             socketIO.adapter(redis({ host: 'localhost', port: 6379 })); | ||||
| @@ -91,17 +119,18 @@ function startSingle(clustered) { | ||||
|             console.log("No redis-server to connect to.."); | ||||
|         } | ||||
|         socketIO.listen(server); | ||||
|         process.on('message', function(message, connection) { | ||||
|             if (message !== 'sticky-session:connection') { | ||||
|                 return; | ||||
|             } | ||||
|             server.emit('connection', connection); | ||||
|  | ||||
|             connection.resume(); | ||||
|         }); | ||||
|     } else { | ||||
|         socketIO.listen(server); | ||||
|     } | ||||
|  | ||||
|     process.on('message', function(message, connection) { | ||||
|         if (message !== 'sticky-session:connection') { | ||||
|             return; | ||||
|         } | ||||
|         server.emit('connection', connection); | ||||
|  | ||||
|         connection.resume(); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function onListen() { | ||||
|   | ||||
| @@ -9,8 +9,8 @@ var app = express(); | ||||
| var exphbs = require('express-handlebars'); | ||||
| 
 | ||||
| var hbs = exphbs.create({ | ||||
| 	defaultLayout: publicPath + '/layouts/main', | ||||
| 	layoutsDir: publicPath + '/layouts', | ||||
| 	defaultLayout: publicPath + '/layouts/client/main', | ||||
| 	layoutsDir: publicPath + '/layouts/client', | ||||
| 	partialsDir: publicPath + '/partials' | ||||
| }); | ||||
| uniqid = require('uniqid'); | ||||
| @@ -60,9 +60,9 @@ emojiStrip = require('emoji-strip'); | ||||
| Filter = require('bad-words'); | ||||
| filter = new Filter({ placeHolder: 'x'}); | ||||
| 
 | ||||
| var router = require('./routing/router.js'); | ||||
| var api = require('./routing/api.js'); | ||||
| var ico_router = require('./routing/icons_routing.js'); | ||||
| var router = require('./routing/client/router.js'); | ||||
| var api = require('./routing/client/api.js'); | ||||
| var ico_router = require('./routing/client/icons_routing.js'); | ||||
| 
 | ||||
| app.get('/robots.txt', function (req, res) { | ||||
| 	res.type('text/plain'); | ||||
							
								
								
									
										24
									
								
								server/models/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,24 @@ | ||||
| // app/models/user.js | ||||
| // load the things we need | ||||
| var mongoose = require('mongoose'); | ||||
| var bcrypt   = require('bcrypt-nodejs'); | ||||
|  | ||||
| // define the schema for our user model | ||||
| var userSchema = mongoose.Schema({ | ||||
|       username     : String, | ||||
|       password     : String, | ||||
| }); | ||||
|  | ||||
| // methods ====================== | ||||
| // generating a hash | ||||
| userSchema.methods.generateHash = function(password) { | ||||
|     return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); | ||||
| }; | ||||
|  | ||||
| // checking if password is valid | ||||
| userSchema.methods.validPassword = function(password) { | ||||
|     return bcrypt.compareSync(password, this.password); | ||||
| }; | ||||
|  | ||||
| // create the model for users and expose it to our app | ||||
| module.exports = mongoose.model('User', userSchema); | ||||
							
								
								
									
										527
									
								
								server/public/assets/admin/authenticated/js/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,527 @@ | ||||
| var connection_options = { | ||||
| 	'sync disconnect on unload':true, | ||||
| 	'secure': true, | ||||
| 	'force new connection': true | ||||
| }; | ||||
| var socket = io.connect('https://zoff.me:8080', connection_options); | ||||
|  | ||||
| $(document).ready(function(){ | ||||
| 	 $('ul.tabs').tabs(); | ||||
|  }); | ||||
|  | ||||
| $(document).on("click", "#refresh_all", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	$("#descriptions_cont").empty(); | ||||
| 	$("#thumbnails_cont").empty(); | ||||
| 	if(!$(".channel_things").hasClass("hide")) { | ||||
| 		$(".channel_things").addClass("hide") | ||||
| 	} | ||||
| 	$(".preloader-wrapper").removeClass("hide"); | ||||
| 	$.ajax({ | ||||
| 		type: "GET", | ||||
| 		url: "/api/lists", | ||||
| 		success: function(response){ | ||||
| 			var output_pinned = '<option value="" disabled>Channels</option>'; | ||||
| 			var output_delete = '<option value="" disabled>Channels</option>'; | ||||
| 			for(var x = 0; x < response.length; x++){ | ||||
| 				if(response[x].count > 5){ | ||||
| 					output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 				} | ||||
| 				output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 			} | ||||
|  | ||||
| 			$("#frontpage_pinned").html(output_pinned); | ||||
| 			$("#remove_thumbnail").html(output_delete); | ||||
| 			$("#remove_description").html(output_delete); | ||||
| 			$("#delete_list_name").html(output_delete); | ||||
| 			$("#delete_userpass_name").html(output_delete); | ||||
| 			$("#delete_channel_name").html(output_delete); | ||||
| 			$("select").material_select(); | ||||
| 			$(".channel_things").removeClass("hide"); | ||||
| 			if(!$(".preloader-wrapper").hasClass("hide")) { | ||||
| 		    	$(".preloader-wrapper").addClass("hide"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	$.ajax({ | ||||
| 		type: "GET", | ||||
| 		url: "/api/thumbnails", | ||||
| 		success: function(response){ | ||||
| 			if(response.length > 0){ | ||||
| 				$(".thumbnails-badge").removeClass("hide"); | ||||
| 				$(".thumbnails-badge").text(response.length); | ||||
| 			} | ||||
| 			add_to_tab("thumbnails", response); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	$.ajax({ | ||||
| 		type: "GET", | ||||
| 		url: "/api/descriptions", | ||||
| 		success: function(response){ | ||||
| 			if(response.length > 0){ | ||||
| 				$(".descriptions-badge").removeClass("hide"); | ||||
| 				$(".descriptions-badge").text(response.length); | ||||
| 			} | ||||
| 			add_to_tab("descriptions", response); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	$("#listeners").empty(); | ||||
| 	socket.emit("get_spread"); | ||||
| }); | ||||
|  | ||||
| socket.on("spread_listeners", function(obj){ | ||||
| 	$("#listeners").append("<p>Private listeners: " + obj.offline + "</p>"); | ||||
| 	$("#listeners").append("<p>Total listeners: " + obj.total + "</p>"); | ||||
| 	$("#listeners").append("<hr>"); | ||||
| 	for(var x in obj.online_users){ | ||||
| 		if(obj.online_users[x]._id != "total_users" && obj.online_users[x].hasOwnProperty("users") && obj.online_users[x].users.length > 0){ | ||||
| 			$("#listeners").append("<p>" + obj.online_users[x]._id + ": " + obj.online_users[x].users.length + "</p>"); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| if(!$(".channel_things").hasClass("hide")) { | ||||
| 	$(".channel_things").addClass("hide") | ||||
| } | ||||
| $(".preloader-wrapper").removeClass("hide"); | ||||
|  | ||||
| $.ajax({ | ||||
| 	type: "GET", | ||||
| 	url: "/api/lists", | ||||
| 	success: function(response){ | ||||
| 		var output_pinned = '<option value="" disabled selected>Channels</option>'; | ||||
| 		var output_delete = '<option value="" disabled selected>Channels</option>'; | ||||
| 		for(var x = 0; x < response.length; x++){ | ||||
| 			if(response[x].count > 5){ | ||||
| 				output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 			} | ||||
| 			output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 		} | ||||
|  | ||||
| 		$("#frontpage_pinned").html(output_pinned); | ||||
| 		$("#remove_thumbnail").html(output_delete); | ||||
| 		$("#remove_description").html(output_delete); | ||||
| 		$("#delete_list_name").html(output_delete); | ||||
| 		$("#delete_userpass_name").html(output_delete); | ||||
| 		$("#delete_channel_name").html(output_delete); | ||||
| 		$("select").material_select(); | ||||
|  | ||||
| 		if(!$(".preloader-wrapper").hasClass("hide")) { | ||||
| 			$(".preloader-wrapper").addClass("hide") | ||||
| 		} | ||||
| 		$(".channel_things").removeClass("hide"); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| $.ajax({ | ||||
|     type: "GET", | ||||
|     url: "/api/names", | ||||
|     success: function(response) { | ||||
| 		for(var i = 0; i < response.length; i++) { | ||||
| 			var icon = ""; | ||||
| 			if(response[i].icon && response[i].icon != "") { | ||||
| 				icon = "<img class='chat-icon' src='" + response[i].icon + "' alt='" + response[i]._id + "'>"; | ||||
| 			} | ||||
| 			$(".names-container").append("<div class='col s12'><div class='name-chat col s3'>" + icon + response[i]._id + "</div><input type='text' class='" + response[i]._id + "_input col s7'><a class='btn green waves-effect col s2 m1 approve_name' href='#' data-name='" + response[i]._id + "'><i class='material-icons'>check</i></a></div>"); | ||||
| 		} | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| $.ajax({ | ||||
| 	type: "GET", | ||||
| 	url: "/api/thumbnails", | ||||
| 	success: function(response){ | ||||
| 		if(response.length > 0){ | ||||
| 			$(".thumbnails-badge").removeClass("hide"); | ||||
| 			$(".thumbnails-badge").text(response.length); | ||||
| 		} | ||||
| 		add_to_tab("thumbnails", response); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".approve_name", function(e) { | ||||
| 	var that = this; | ||||
| 	var name = $(that).attr("data-name"); | ||||
| 	var value = $("." + name + "_input").val(); | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/names", | ||||
| 		data: { | ||||
| 			icon: value, | ||||
| 			name: name, | ||||
| 		}, | ||||
| 		success: function(resp) { | ||||
| 			if(resp == true) { | ||||
| 				Materialize.toast("Approved image!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".thumbnail_link", function(e) { | ||||
| 	e.preventDefault(); | ||||
| 	window.open("https:" + this.value,'_blank'); | ||||
| }); | ||||
|  | ||||
| $.ajax({ | ||||
| 	type: "GET", | ||||
| 	url: "/api/descriptions", | ||||
| 	success: function(response){ | ||||
| 		if(response.length > 0){ | ||||
| 			$(".descriptions-badge").removeClass("hide"); | ||||
| 			$(".descriptions-badge").text(response.length); | ||||
| 		} | ||||
| 		add_to_tab("descriptions", response); | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| function add_to_tab(dest, resp){ | ||||
| 	for(var x = 0; x < resp.length; x++){ | ||||
| 		if(dest == "thumbnails"){ | ||||
| 			$("#" + dest + "_cont").append("<div><div class='col s4 m3'>" + resp[x].channel + "</div><input type='text' readonly class='col s4 m6 thumbnail_link' value='" + resp[x].thumbnail + "'><a class='btn green waves-effect col s2 m1 approve_" + dest + "' href='#' data-channel='" + resp[x].channel + "'><i class='material-icons'>check</i></a><a class='btn red waves-effect col s2 m1 deny_" + dest + "' href='#' data-channel='" + resp[x].channel + "'>X</a></div>"); | ||||
| 		} else { | ||||
| 			$("#" + dest + "_cont").append("<div><div class='col s4 m3'>" + resp[x].channel + "</div><input type='text' readonly class='col s4 m6' value='" + resp[x].description + "'><a class='btn green waves-effect col s2 m1 approve_" + dest + "' href='#' data-channel='" + resp[x].channel + "'><i class='material-icons'>check</i></a><a class='btn red waves-effect col s2 m1 deny_" + dest + "' href='#' data-channel='" + resp[x].channel + "'>X</a></div>"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $(document).on("click", "#get_token", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	$.ajax({ | ||||
| 		type: "GET", | ||||
| 		url: "/api/token", | ||||
| 		success: function(response){ | ||||
| 			if(response != false){ | ||||
| 				$("#new_token").val(response.token); | ||||
| 				$("#get_token").toggleClass("hide"); | ||||
| 				$("#remove_token").toggleClass("hide"); | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".approve_thumbnails", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $(this).attr("data-channel"); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/approve_thumbnail", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				$(that).parent().remove(); | ||||
| 				var length = parseInt($(".thumbnails-badge").text()); | ||||
| 				length = length - 1; | ||||
| 				$(".thumbnails-badge").text(length); | ||||
| 				if(length <= 0 && !$(".thumbnails-badge").hasClass("hide")){ | ||||
| 					$(".thumbnails-badge").addClass("hide"); | ||||
| 				} | ||||
| 				Materialize.toast("Approved Thumbnail!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".deny_thumbnails", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $(this).attr("data-channel"); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/deny_thumbnail", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				$(that).parent().remove(); | ||||
| 				var length = parseInt($(".thumbnails-badge").text()); | ||||
| 				length = length - 1; | ||||
| 				$(".thumbnails-badge").text(length); | ||||
| 				if(length <= 0 && !$(".thumbnails-badge").hasClass("hide")){ | ||||
| 					$(".thumbnails-badge").addClass("hide"); | ||||
| 				} | ||||
| 				Materialize.toast("Denied thumbnail!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".approve_descriptions", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $(this).attr("data-channel"); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/approve_description", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				$(that).parent().remove(); | ||||
| 				var length = parseInt($(".descriptions-badge").text()); | ||||
| 				length = length - 1; | ||||
| 				$(".descriptions-badge").text(length); | ||||
| 				if(length <= 0 && !$(".descriptions-badge").hasClass("hide")){ | ||||
| 					$(".descriptions-badge").addClass("hide"); | ||||
| 				} | ||||
| 				Materialize.toast("Approved description!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", ".deny_descriptions", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $(this).attr("data-channel"); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/deny_description", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				$(that).parent().remove(); | ||||
| 				var length = parseInt($(".descriptions-badge").text()); | ||||
| 				length = length - 1; | ||||
| 				$(".descriptions-badge").text(length); | ||||
| 				if(length <= 0 && !$(".descriptions-badge").hasClass("hide")){ | ||||
| 					$(".descriptions-badge").addClass("hide"); | ||||
| 				} | ||||
| 				Materialize.toast("Denied description!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#remove_description_button", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $("#remove_description").val(); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/remove_description", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				Materialize.toast("Removed description!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#remove_thumbnail_button", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var channel = $("#remove_thumbnail").val(); | ||||
| 	if(!channel) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var that = this; | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/remove_thumbnail", | ||||
| 		data: { | ||||
| 			channel: channel | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response){ | ||||
| 				Materialize.toast("Removed thumbnail!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| }); | ||||
|  | ||||
| $(document).on("submit", "#delete_channel", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var to_delete = $("#delete_channel_name").val(); | ||||
| 	if(!to_delete) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	var r = confirm("Delete list " + to_delete + "?"); | ||||
| 	if (r == true) { | ||||
| 		$.ajax({ | ||||
| 			type: "POST", | ||||
| 			url: "/api/delete", | ||||
| 			data: { | ||||
| 				_id: to_delete | ||||
| 			}, | ||||
| 			success: function(response){ | ||||
| 				if(response == true){ | ||||
| 					$.ajax({ | ||||
| 						type: "GET", | ||||
| 						url: "/api/lists", | ||||
| 						success: function(response){ | ||||
| 							var output_pinned = ""; | ||||
| 							var output_delete = ""; | ||||
| 							for(var x = 0; x < response.length; x++){ | ||||
| 								if(response[x].count > 5){ | ||||
| 									output_pinned += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 								} | ||||
| 								output_delete += "<option class='" + response[x]._id + "' value='" + response[x]._id + "'>" + response[x]._id + "</option>"; | ||||
| 							} | ||||
|  | ||||
| 							$("#frontpage_pinned").html(output_pinned); | ||||
| 							$("#delete_list_name").html(output_delete); | ||||
| 							$("#delete_userpass_name").html(output_delete); | ||||
| 							$("#delete_channel_name").html(output_delete); | ||||
| 							$("select").material_select(); | ||||
| 						} | ||||
| 					}); | ||||
| 					Materialize.toast("Deleted channel!", 2000, "green lighten"); | ||||
| 				} else { | ||||
| 					Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#delete_channel_button", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	$("#delete_channel").submit(); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#remove_token", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	$.ajax({ | ||||
| 		type: "GET", | ||||
| 		url: "/api/remove_token", | ||||
| 		success: function(response){ | ||||
| 			if(response != false){ | ||||
| 				$("#new_token").val(""); | ||||
| 				$("#get_token").toggleClass("hide"); | ||||
| 				$("#remove_token").toggleClass("hide"); | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| }); | ||||
|  | ||||
| $(document).on("submit", "#change_pinned", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var to_pin = $("#frontpage_pinned").val(); | ||||
| 	if(!to_pin) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/pinned", | ||||
| 		data: { | ||||
| 			_id: to_pin | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response == true){ | ||||
| 				Materialize.toast("Pinned channel!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#change_pinned_button", function(){ | ||||
| 	$("#change_pinned").submit(); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#delete_admin_button", function(){ | ||||
| 	$("#delete_list").submit(); | ||||
| }); | ||||
|  | ||||
| $(document).on("click", "#delete_userpass_button", function(){ | ||||
| 	$("#delete_userpass").submit(); | ||||
| }); | ||||
|  | ||||
| $(document).on("submit", "#delete_list", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var to_remove_password = $("#delete_list_name").val(); | ||||
| 	if(!to_remove_password) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/admin", | ||||
| 		data: { | ||||
| 			_id: to_remove_password | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response == true){ | ||||
| 				Materialize.toast("Removed admin password!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| }); | ||||
|  | ||||
| $(document).on("submit", "#delete_userpass", function(e){ | ||||
| 	e.preventDefault(); | ||||
| 	var to_remove_password = $("#delete_userpass_name").val(); | ||||
| 	if(!to_remove_password) { | ||||
| 		Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 		return; | ||||
| 	} | ||||
| 	$.ajax({ | ||||
| 		type: "POST", | ||||
| 		url: "/api/userpass", | ||||
| 		data: { | ||||
| 			_id: to_remove_password | ||||
| 		}, | ||||
| 		success: function(response){ | ||||
| 			if(response == true){ | ||||
| 				Materialize.toast("Removed userpass password!", 2000, "green lighten"); | ||||
| 			} else { | ||||
| 				Materialize.toast("Something went wrong...", 2000, "red lighten"); | ||||
| 			} | ||||
| 		} | ||||
| 	}) | ||||
| }); | ||||
|  | ||||
| socket.emit("get_spread"); | ||||
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/144x144.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 6.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/GitHub_Logo.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/Logo.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 36 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/facebook.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 697 B | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/favicon.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 56 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/glight.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/gmark.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/google_play.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 6.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/highlogo.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 66 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/loading.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 786 B | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/pin.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 299 B | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/q.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/s1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/s2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/s3.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/spotify.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/squareicon.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 37 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/squareicon_small.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/squareicon_small_old.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 24 KiB | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/twitter.png
									
									
									
									
									
										Executable file
									
								
							
							
						
						| After Width: | Height: | Size: 980 B | 
							
								
								
									
										
											BIN
										
									
								
								server/public/assets/admin/images/youtube.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 6.0 KiB | 
							
								
								
									
										18
									
								
								server/public/assets/admin/not_authenticated/js/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,18 @@ | ||||
| $(document).on("click", "#login_button", function(e){ | ||||
|   e.preventDefault(); | ||||
|   $("#login_form").submit(); | ||||
| }) | ||||
|  | ||||
| $(document).ready(function(){ | ||||
|   if(window.location.pathname == "/signup/" || window.location.pathname == "/signup"){ | ||||
|     $("#login_form").prepend("<input type='text' name='token' placeholder='Token' required autocomplete='off' />"); | ||||
|     $("#login_form").attr("action", "/signup"); | ||||
|   } | ||||
| }); | ||||
|  | ||||
|  | ||||
| $(document).on("submit", "#login_form", function(e){ | ||||
|   if(this.password.value == "" || this.username.value == ""){ | ||||
|     e.preventDefault(); | ||||
|   } | ||||
| }) | ||||
							
								
								
									
										172
									
								
								server/public/layouts/admin/authenticated.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,172 @@ | ||||
| <header> | ||||
|     <nav id="fp-nav"> | ||||
|         <div class="nav-wrapper"> | ||||
|             <a href="#" class="brand-logo noselect"> | ||||
|                 <img class="zicon" src="/assets/images/squareicon_small.png" alt="Zoff" title="Zoff" /> | ||||
|             </a> | ||||
|             <ul class="right"> | ||||
|                 <li><a class="header-buttons waves-effect waves-cyan" id="logout" title="Logout" href="/logout">Logout</a></li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </nav> | ||||
| </header> | ||||
| <main class="container center-align admin_panel"> | ||||
|   <div class="row"> | ||||
|     <h2 class="col s11">Admin</h2> | ||||
|     <a href="#" id="refresh_all" class="col s1"><h2><i class="material-icons">refresh</i></h2></a> | ||||
|   </div> | ||||
|   <div class="row"> | ||||
|     <div class="col s12 m10"> | ||||
|       <ul class="tabs tabs_admin"> | ||||
|         <li class="tab col s3"><a class="active" href="#general">General</a></li> | ||||
|         <li class="tab col s3"><a href="#thumbnails">Thumbnails<span class="new thumbnails-badge badge admin-panel hide"></span></a></li> | ||||
|         <li class="tab col s3"><a href="#descriptions">Descriptions<span class="new descriptions-badge badge admin-panel hide"></span></a></li> | ||||
|         <li class="tab col s3"><a href="#names">Names</a></li> | ||||
|       </ul> | ||||
|       <div id="general" class="col s12"> | ||||
|         <div class="preloader-wrapper big active"> | ||||
|           <div class="spinner-layer spinner-zoff-only"> | ||||
|             <div class="circle-clipper left"> | ||||
|               <div class="circle"></div> | ||||
|             </div><div class="gap-patch"> | ||||
|               <div class="circle"></div> | ||||
|             </div><div class="circle-clipper right"> | ||||
|               <div class="circle"></div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="channel_things hide"> | ||||
|           <form id="change_pinned"> | ||||
|             <div class="row"> | ||||
|               <div class="input-field col s8 m10"> | ||||
|                 <select id="frontpage_pinned"> | ||||
|                   <option value="" disabled>Channels</option> | ||||
|                 </select> | ||||
|                 <label>Change Pinned</label> | ||||
|               </div> | ||||
|               <div class="col s2"> | ||||
|                 <a href="#" id="change_pinned_button" class="btn green waves-effect">UPDATE</a> | ||||
|               </div> | ||||
|             </div> | ||||
|           </form> | ||||
|           <form id="delete_list"> | ||||
|             <div class="row"> | ||||
|               <div class="input-field col s8 m10"> | ||||
|                 <select id="delete_list_name"> | ||||
|                   <option value="" disabled>Channels</option> | ||||
|                 </select> | ||||
|                 <label>Delete Admin</label> | ||||
|               </div> | ||||
|               <div class="col s2"> | ||||
|                 <a href="#" id="delete_admin_button" class="btn orange waves-effect">UPDATE</a> | ||||
|               </div> | ||||
|             </div> | ||||
|           </form> | ||||
|           <form id="delete_userpass"> | ||||
|             <div class="row"> | ||||
|               <div class="input-field col s8 m10"> | ||||
|                 <select id="delete_userpass_name"> | ||||
|                   <option value="" disabled>Channels</option> | ||||
|                 </select> | ||||
|                 <label>Delete Userpass</label> | ||||
|               </div> | ||||
|               <div class="col s2"> | ||||
|                 <a href="#" id="delete_userpass_button" class="btn blue waves-effect">UPDATE</a> | ||||
|               </div> | ||||
|             </div> | ||||
|           </form> | ||||
|           <form id="delete_channel"> | ||||
|             <div class="row"> | ||||
|               <div class="input-field col s8 m10"> | ||||
|                 <select id="delete_channel_name"> | ||||
|                   <option value="" disabled>Channels</option> | ||||
|                 </select> | ||||
|                 <label>Delete Channel</label> | ||||
|               </div> | ||||
|               <div class="col s2"> | ||||
|                 <a href="#" id="delete_channel_button" class="btn red waves-effect">DELETE</a> | ||||
|               </div> | ||||
|             </div> | ||||
|           </form> | ||||
|  | ||||
|           <div class="row"> | ||||
|             <div class="input-field col s8 m10"> | ||||
|               <input type="text" readonly id="new_token" /> | ||||
|             </div> | ||||
|             <div class="col s2"> | ||||
|               <a href="#" id="get_token" class="btn waves-effect">TOKEN</a> | ||||
|               <a href="#" id="remove_token" class="btn red waves-effect hide">REMOVE</a> | ||||
|             </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div id="thumbnails" class="col s12"> | ||||
|       <div class="row"> | ||||
|         <div class="input-field col s8 m10"> | ||||
|           <select id="remove_thumbnail"> | ||||
|             <option value="" disabled>Channels</option> | ||||
|           </select> | ||||
|           <label>Remove Thumbnail</label> | ||||
|         </div> | ||||
|         <div class="col s2"> | ||||
|           <a href="#" id="remove_thumbnail_button" class="btn red waves-effect">REMOVE</a> | ||||
|         </div> | ||||
|         <div id="thumbnails_cont" class="col s12"> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div id="descriptions" class="col s12"> | ||||
|       <div class="row"> | ||||
|         <div class="input-field col s8 m10"> | ||||
|           <select id="remove_description"> | ||||
|             <option value="" disabled>Channels</option> | ||||
|           </select> | ||||
|           <label>Remove Description</label> | ||||
|         </div> | ||||
|         <div class="col s2"> | ||||
|           <a href="#" id="remove_description_button" class="btn red waves-effect">REMOVE</a> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div id="descriptions_cont" class="col s12"> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div id="names" class="col s12"> | ||||
|         <div class="row names-container"> | ||||
|  | ||||
|         </div> | ||||
|     </div> | ||||
|     </div> | ||||
|     <div class="col s10 m2 left-align" id="listeners"> | ||||
|       <div class="row"> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </main> | ||||
| <footer class="page-footer cursor-default"> | ||||
| <div class="container"> | ||||
|     <div class="row"> | ||||
|         <div class="col l6 s12"> | ||||
|             <h5 class="white-text">Zoff</h5> | ||||
|             <p class="grey-text text-lighten-4">The shared YouTube radio</p> | ||||
|             <p class="grey-text text-lighten-4"> | ||||
|                 Being built around the YouTube search and video API | ||||
|                 it enables the creation of collaborative and shared live playlists, | ||||
|                 with billions of videos and songs to choose from, all for free and without registration. | ||||
|                 <br /> | ||||
|                 Enjoy! | ||||
|             </p> | ||||
|         </div> | ||||
|         <div class="col l4 offset-l2 s12 valign-wrapper"> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <div class="footer-copyright"> | ||||
|     <div class="container"> | ||||
|         © {{year}} | ||||
|         <a href="http://nixo.no">Nixo</a> & | ||||
|         <a href="http://kasperrt.no">KasperRT</a> | ||||
|         <br> | ||||
|         All Rights Reserved. | ||||
|     </div> | ||||
| </div> | ||||
| </footer> | ||||
							
								
								
									
										70
									
								
								server/public/layouts/admin/main.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,70 @@ | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|   <head> | ||||
|     <meta charset="utf-8" /> | ||||
|     <title> | ||||
|       Zoff Admin | ||||
|     </title> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"> | ||||
|     <meta name="apple-mobile-web-app-capable" content="yes"> | ||||
|     <meta name="mobile-web-app-capable" content="yes"> | ||||
|     <meta name="theme-color" content="#2D2D2D"> | ||||
|     <meta property="og:image" content="https://zoff.me/assets/images/favicon.png"> | ||||
|     <meta property="og:url" content="https://admin.zoff.me"> | ||||
|     <meta property="og:title" content="Zoff Admin"> | ||||
|     <meta property="og:description" content="Zoff admin panel"> | ||||
|     <meta property="og:type" content="website"> | ||||
|     <link rel="icon" id="favicon" type="image/png" href="https://zoff.me/assets/images/favicon.png"> | ||||
|     <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> | ||||
|     <script | ||||
|   src="https://code.jquery.com/jquery-2.2.4.min.js" | ||||
|   integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" | ||||
|   crossorigin="anonymous"></script> | ||||
|   <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css"> | ||||
|  | ||||
| <!-- Compiled and minified JavaScript --> | ||||
| <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script> | ||||
|  | ||||
|     <link rel="stylesheet" type="text/css" href="https://zoff.me/assets/css/style.css" title="Default" /> | ||||
|     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script> | ||||
|     <script type="text/javascript" src="/assets/admin/{{{where_get}}}/js/main.js"></script> | ||||
|     <style> | ||||
|       .preloader-wrapper { | ||||
|         margin-top:15%; | ||||
|       } | ||||
|  | ||||
|       .spinner-zoff-only { | ||||
|         border-color: #2d2d2d !important; | ||||
|       } | ||||
|       .tab a{ | ||||
|         color: black !important; | ||||
|       } | ||||
|  | ||||
|       .name-chat { | ||||
|         display: flex; | ||||
|         flex-direction: row; | ||||
|         align-items: center; | ||||
|         justify-content: center; | ||||
|       } | ||||
|  | ||||
|       .chat-icon { | ||||
|         width: 16px; | ||||
|         height: auto; | ||||
|         margin-right: 2px; | ||||
|       } | ||||
|  | ||||
|       .tabs_admin{ | ||||
|         margin-bottom:20px; | ||||
|       } | ||||
|  | ||||
|       .tabs_admin .indicator{ | ||||
|         width: initial !important; | ||||
|         background: black !important; | ||||
|       } | ||||
|  | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     {{{body}}} | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										11
									
								
								server/public/layouts/admin/not_authenticated.handlebars
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,11 @@ | ||||
| <main class="container valign-wrapper row"> | ||||
|       <div class="center-align col m6 offset-m3"> | ||||
|         <img src="https://zoff.me/assets/images/favicon.png" width="100" height="100" alt="image" /> | ||||
|         <form action="/login" id="login_form" method="POST"> | ||||
|           <input type="text" name="username" placeholder="Username" required autofocus="on" autocomplete="off" /> | ||||
|           <input type="password" name="password" placeholder="Password" required /> | ||||
|           <input type="submit" class="hide"> | ||||
|           <a href="#" class="btn grey darken-3 waves-effect" id="login_button">LOGIN</a> | ||||
|         </form> | ||||
|       </div> | ||||
| </main> | ||||
							
								
								
									
										230
									
								
								server/routing/admin/api.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,230 @@ | ||||
| var express = require('express'); | ||||
| var router = express.Router(); | ||||
| var path = require('path'); | ||||
| var mongo_db_cred = require(path.join(__dirname, '../../config/mongo_config.js')); | ||||
| var mongojs = require('mongojs'); | ||||
| var db = mongojs(mongo_db_cred.config); | ||||
|  | ||||
| router.use(function(req, res, next) { | ||||
|     next(); // make sure we go to the next routes and don't stop here | ||||
| }); | ||||
|  | ||||
| router.route('/api/lists').get(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       db.collection("frontpage_lists").find().sort({count: -1},function(err, docs){ | ||||
|          res.json(docs); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/thumbnails').get(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       db.collection("suggested_thumbnails").find(function(err, docs){ | ||||
|          res.json(docs); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/descriptions').get(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       db.collection("suggested_descriptions").find(function(err, docs){ | ||||
|          res.json(docs); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/approve_thumbnail').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("suggested_thumbnails").find({channel: channel}, function(err, docs){ | ||||
|          var thumbnail = docs[0].thumbnail; | ||||
|          db.collection("frontpage_lists").update({_id: channel}, {$set:{thumbnail: thumbnail}}, {upsert: true}, function(err, docs){ | ||||
|             db.collection(channel).update({views:{$exists:true}}, {$set:{thumbnail: thumbnail}}, {upsert: true}, function(err, docs){ | ||||
|                db.collection("suggested_thumbnails").remove({channel: channel}, function(err, docs){ | ||||
|                   res.send(true); | ||||
|                }); | ||||
|             }); | ||||
|          }); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/deny_thumbnail').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("suggested_thumbnails").remove({channel: channel},function(err, docs){ | ||||
|          res.send(true); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/approve_description').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("suggested_descriptions").find({channel: channel}, function(err, docs){ | ||||
|          var description = docs[0].description; | ||||
|          db.collection("frontpage_lists").update({_id: channel}, {$set:{description: description}}, {upsert: true}, function(err, docs){ | ||||
|            db.collection(channel).update({views:{$exists:true}}, {$set:{description: description}}, function(err, docs){ | ||||
|              db.collection("suggested_descriptions").remove({channel: channel}, function(err, docs){ | ||||
|                 res.send(true); | ||||
|               }); | ||||
|             }); | ||||
|           }); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/deny_description').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("suggested_descriptions").remove({channel: channel}, 1,function(err, docs){ | ||||
|          res.send(true); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/remove_thumbnail').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("frontpage_lists").update({_id: channel}, {$set:{thumbnail: ""}}, function(err, docs){ | ||||
|          db.collection(channel).update({views:{$exists:true}}, {$set:{thumbnail: ""}}, function(err, docs){ | ||||
|             res.send(true); | ||||
|          }); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/remove_description').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var channel = req.param("channel"); | ||||
|       db.collection("frontpage_lists").update({_id: channel}, {$set:{description: ""}}, function(err, docs){ | ||||
|          db.collection(channel).update({views:{$exists:true}}, {$set:{description: ""}}, function(err, docs){ | ||||
|             res.send(true); | ||||
|          }); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/names').get(function(req, res) { | ||||
|    if(req.isAuthenticated()){ | ||||
|       db.collection("registered_users").find({_id: {$exists: true}}, {_id: 1, icon: 1}, function(err, docs) { | ||||
|          res.json(docs); | ||||
|       }) | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/names').post(function(req, res) { | ||||
|    if(req.isAuthenticated()) { | ||||
|       var icon = req.param("icon"); | ||||
|       var name = req.param("name"); | ||||
|       db.collection("registered_users").update({_id: name}, {$set: {icon: icon}}, function(err, docs) { | ||||
|          if(err) res.send(false); | ||||
|          else res.send(true); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }) | ||||
|  | ||||
| router.route('/api/token').get(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       token_db.collection("tokens").find(function(err, docs){ | ||||
|          if(docs.length == 1){ | ||||
|             res.json({token: docs[0].token}); | ||||
|          } else { | ||||
|             var id = new Buffer(makeid()).toString('base64'); | ||||
|             token_db.collection("tokens").insert({token: id}, function(err, docs){ | ||||
|                res.json({token: id}); | ||||
|             }); | ||||
|          } | ||||
|       }) | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/delete').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var list = req.param("_id"); | ||||
|       db.collection(list).drop(function(err, docs){ | ||||
|          db.collection("frontpage_lists").remove({_id: list}, function(err, docs){ | ||||
|             res.send(true); | ||||
|          }) | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/remove_token').get(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       token_db.collection("tokens").find(function(err, docs){ | ||||
|          if(docs.length == 1){ | ||||
|             token_db.collection("tokens").remove({token: docs[0].token}, function(err, docs){ | ||||
|                res.send(true); | ||||
|             }) | ||||
|          } else { | ||||
|             res.send(false); | ||||
|          } | ||||
|       }) | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/pinned').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var to_pin = req.param("_id"); | ||||
|       db.collection("frontpage_lists").update({pinned:1}, {$set:{pinned:0}}, function(err, resp){ | ||||
|         	db.collection("frontpage_lists").update({_id:to_pin}, {$set:{pinned:1}}, function(err, resp){ | ||||
|         		res.send(true); | ||||
|         	}); | ||||
|         }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/admin').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var to_remove = req.param("_id"); | ||||
|       db.collection(to_remove).update({views: {$exists: true}}, {$set:{adminpass: ""}}, function(err, docs){ | ||||
|          res.send(true); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| router.route('/api/userpass').post(function(req, res){ | ||||
|    if(req.isAuthenticated()){ | ||||
|       var to_remove = req.param("_id"); | ||||
|       db.collection(to_remove).update({views: {$exists: true}}, {$set:{userpass: ""}}, function(err, docs){ | ||||
|          res.send(true); | ||||
|       }); | ||||
|    } else { | ||||
|       res.send(false); | ||||
|    } | ||||
| }); | ||||
|  | ||||
| module.exports = router; | ||||
| @@ -94,8 +94,8 @@ router.route('/api/imageblob').post(function(req, res) { | ||||
| 
 | ||||
| var nodemailer = require('nodemailer'); | ||||
| try { | ||||
|     var mailconfig = require(path.join(__dirname, '../config/mailconfig.js')); | ||||
|     var recaptcha_config = require(path.join(__dirname, '../config/recaptcha.js')); | ||||
|     var mailconfig = require(path.join(__dirname, '../../config/mailconfig.js')); | ||||
|     var recaptcha_config = require(path.join(__dirname, '../../config/recaptcha.js')); | ||||
|     var Recaptcha = require('express-recaptcha'); | ||||
|     var RECAPTCHA_SITE_KEY = recaptcha_config.site; | ||||
|     var RECAPTCHA_SECRET_KEY = recaptcha_config.key; | ||||
| @@ -6,7 +6,7 @@ var path = require('path'); | ||||
| 
 | ||||
| try { | ||||
|     var Recaptcha = require('express-recaptcha'); | ||||
|     var recaptcha_config = require(path.join(path.join(__dirname, '../config/'), 'recaptcha.js')); | ||||
|     var recaptcha_config = require(path.join(path.join(__dirname, '../../config/'), 'recaptcha.js')); | ||||
|     var RECAPTCHA_SITE_KEY = recaptcha_config.site; | ||||
|     var RECAPTCHA_SECRET_KEY = recaptcha_config.key; | ||||
|     var recaptcha = new Recaptcha(RECAPTCHA_SITE_KEY, RECAPTCHA_SECRET_KEY); | ||||
| @@ -56,7 +56,7 @@ function root(req, res, next) { | ||||
|                 javascript_file: "remote.min.js", | ||||
|                 captcha: res.recaptcha | ||||
|             } | ||||
|             res.render('layouts/remote', data); | ||||
|             res.render('layouts/client/remote', data); | ||||
|         } else if(subdomain[0] == "www") { | ||||
|             res.redirect("https://zoff.me"); | ||||
|         } else { | ||||
| @@ -65,7 +65,7 @@ function root(req, res, next) { | ||||
|                 javascript_file: "main.min.js", | ||||
|                 captcha: res.recaptcha | ||||
|             } | ||||
|             res.render('layouts/frontpage', data); | ||||
|             res.render('layouts/client/frontpage', data); | ||||
|         } | ||||
|     } catch(e) { | ||||
|         //console.log(e);
 | ||||
| @@ -87,7 +87,7 @@ function channel(req, res, next) { | ||||
|                 javascript_file: "remote.min.js", | ||||
|                 captcha: res.recaptcha | ||||
|             } | ||||
|             res.render('layouts/remote', data); | ||||
|             res.render('layouts/client/remote', data); | ||||
|         } else if(subdomain.length >= 2 && subdomain[0] == "www") { | ||||
|             res.redirect("https://zoff.me"); | ||||
|         } else { | ||||
| @@ -109,7 +109,7 @@ function channel(req, res, next) { | ||||
|                     res.status(404); | ||||
|                 } | ||||
| 
 | ||||
|                 res.render('layouts/channel', data); | ||||
|                 res.render('layouts/client/channel', data); | ||||
|             } | ||||
|         } | ||||
|     } catch(e) { | ||||