mirror of
https://github.com/diced/zipline.git
synced 2025-12-22 23:26:36 -08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e1c71f541 | ||
|
|
7c6f30544a | ||
|
|
31082b4600 | ||
|
|
e8a1b23f51 | ||
|
|
e99a6a2740 | ||
|
|
93a8f3a854 | ||
|
|
7313866a42 | ||
|
|
9933f7396a | ||
|
|
aea325aac8 | ||
|
|
ef97cae957 | ||
|
|
dc1664fa71 | ||
|
|
443ed42c2c | ||
|
|
4e66e1bbfc | ||
|
|
4df9a42e7d | ||
|
|
7dc084ae51 | ||
|
|
83b9da31a1 | ||
|
|
eb38206743 | ||
|
|
33ea9547e2 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,9 @@
|
||||
node_modules
|
||||
temp
|
||||
tmp
|
||||
uploads
|
||||
config.json
|
||||
out
|
||||
out
|
||||
public/assets/pd_logo.png
|
||||
ssl/localhost.key
|
||||
ssl/localhost.crt
|
||||
292
README.md
292
README.md
@@ -5,20 +5,27 @@ A TypeScript based Image/File uploading server. Fast and Elegant.
|
||||
## Table of Contents
|
||||
|
||||
1. Prerequisites
|
||||
1. Node
|
||||
2. Common Databases
|
||||
1. Node
|
||||
2. Common Databases
|
||||
3. Installing Database Drivers
|
||||
1. PostgreSQL
|
||||
2. CockroachDB
|
||||
3. MySQL
|
||||
4. MariaDB
|
||||
5. Microsoft SQL Server
|
||||
2. Installation
|
||||
1. Get the Source
|
||||
2. Setting up configurations
|
||||
1. Upload Size
|
||||
2. Site Settings
|
||||
3. Administrator user
|
||||
4. Database configuration
|
||||
5. Session Secret
|
||||
6. Web server port
|
||||
3. Example Config
|
||||
4. Compiling Source
|
||||
5. Running Compiled Source
|
||||
1. Get the Source
|
||||
2. Setting up configurations
|
||||
1. Upload Size
|
||||
2. Site Settings
|
||||
3. SSL Settings
|
||||
4. Administrator user
|
||||
5. Database configuration
|
||||
6. Session Secret
|
||||
7. Particles.JS
|
||||
3. Example Config
|
||||
4. Compiling Source
|
||||
5. Running Compiled Source
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -55,15 +62,59 @@ v13.13.0
|
||||
|
||||
### Common Databases
|
||||
|
||||
* MariaDB
|
||||
* MySQL
|
||||
* PostgreSQL
|
||||
* CockroachDB
|
||||
* Microsoft SQL Server
|
||||
* MongoDB (Coming soon!)
|
||||
- PostgreSQL
|
||||
- CockroachDB
|
||||
- MySQL
|
||||
- MariaDB
|
||||
- Microsoft SQL Server
|
||||
- MongoDB (Coming soon!)
|
||||
|
||||
(check out [this](https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md) for all types, you will need to use a different ORM config later on, view [this](https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md#common-connection-options) for every option, more on this on Database configuration setup step)
|
||||
|
||||
### Installing Database Drivers
|
||||
|
||||
In this installation step, you will be installing the drivers of your choice database.
|
||||
|
||||
#### Getting PostgreSQL Drivers
|
||||
|
||||
Run the following command in order to get PostgreSQL drivers
|
||||
|
||||
```sh
|
||||
npm i pg --save-dev
|
||||
```
|
||||
|
||||
#### Getting CockroachDB Drivers
|
||||
|
||||
Run the following command in order to get CockroachDB drivers
|
||||
|
||||
```sh
|
||||
npm i cockroachdb --save-dev
|
||||
```
|
||||
|
||||
#### Getting MySQL Drivers
|
||||
|
||||
Run the following command in order to get MySQL drivers
|
||||
|
||||
```sh
|
||||
npm i mysql --save-dev
|
||||
```
|
||||
|
||||
#### Getting MariaDB Drivers
|
||||
|
||||
Run the following command in order to get MariaDB drivers
|
||||
|
||||
```sh
|
||||
npm i mariadb --save-dev
|
||||
```
|
||||
|
||||
#### Getting Microsoft SQL Drivers
|
||||
|
||||
Run the following command in order to get Microsoft SQL drivers
|
||||
|
||||
```sh
|
||||
npm i mssql --save-dev
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Now that you have considered what prerequisites you would like, lets actually install this! This installation is based on Linux systems, yet will work on both MacOSX and Windows with their respective commands
|
||||
@@ -88,7 +139,7 @@ Every single configuration option will be listed here
|
||||
**Config Property:** `upload`
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
|---------------------|---------|--------------------------------------------------------------|
|
||||
| ------------------- | ------- | ------------------------------------------------------------ |
|
||||
| `upload.fileLength` | integer | how long the random id for a file should be |
|
||||
| `upload.tempDir` | string | temporary directory, files are stored here and then deleted. |
|
||||
| `upload.uploadDir` | string | upload directory (where all uploads are stored) |
|
||||
@@ -98,16 +149,26 @@ Every single configuration option will be listed here
|
||||
**Config Property:** `site`
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
|-----------------|---------|--------------------------------------------------------|
|
||||
| --------------- | ------- | ------------------------------------------------------ |
|
||||
| `site.protocol` | integer | protocol (http or https) |
|
||||
| `site.domain` | string | domain of server (ex. `localhost:8080`, `example.com`) |
|
||||
| `site.serveHTTP` | string | Port to run the web server on with HTTP (can be used with nginx + CloudFlare as a reverse proxy and let CloudFlare take care of SSL) |
|
||||
| `site.serveHTTPS` | string | Port to run the web server on with HTTPS (only will be used if `site.protocol` is `https`) (you will need SSL certificates! See [this](#ssl-settings)) |
|
||||
|
||||
#### SSL Settings
|
||||
|
||||
**Config Property:** `site.ssl`
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
| --------------- | ------ | ----------------------------------------------- |
|
||||
| `site.ssl.key` | string | path to ssl private key. ex: `./ssl/server.key` |
|
||||
| `site.ssl.cert` | string | path to ssl certificate. ex: `./ssl/cert.crt` |
|
||||
|
||||
#### Administrator User
|
||||
|
||||
**Config Property:** `administrator`
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
|-------------------------------|--------|----------------------------------------------------------------------------------------------------------|
|
||||
| ----------------------------- | ------ | -------------------------------------------------------------------------------------------------------- |
|
||||
| `administrator.password` | string | password of administrator user (NOT RECOMENDED to use administrator user, set this to a SECURE password) |
|
||||
| `administrator.authorization` | string | authorization token that could be used for uploading (NOT RECOMENDED, set this to a SECURE master token) |
|
||||
|
||||
@@ -115,17 +176,17 @@ Every single configuration option will be listed here
|
||||
|
||||
**Config Property:** `orm`
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
|-------------------|----------|------------------------------------------------------|
|
||||
| `orm.type` | string | `mariadb`, `mysql`, `postgres`, `cockroach`, `mssql` |
|
||||
| `orm.host` | string | `localhost` or different IP |
|
||||
| `orm.port` | integer | `5432` or different pot |
|
||||
| `orm.username` | string | username |
|
||||
| `orm.password` | string | password |
|
||||
| `orm.database` | string | database to use |
|
||||
| `orm.synchronize` | boolean | synchronize database to database, or not |
|
||||
| `orm.logging` | boolean | log all queries |
|
||||
| `orm.entities` | string[] | entity paths (should not be edited, and should be `["out/src/entities/**/*.js"]`) |
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
| ----------------- | -------- | --------------------------------------------------------------------------------- |
|
||||
| `orm.type` | string | `mariadb`, `mysql`, `postgres`, `cockroach`, `mssql` |
|
||||
| `orm.host` | string | `localhost` or different IP |
|
||||
| `orm.port` | integer | `5432` or different pot |
|
||||
| `orm.username` | string | username |
|
||||
| `orm.password` | string | password |
|
||||
| `orm.database` | string | database to use |
|
||||
| `orm.synchronize` | boolean | synchronize database to database, or not |
|
||||
| `orm.logging` | boolean | log all queries |
|
||||
| `orm.entities` | string[] | entity paths (should not be edited, and should be `["out/src/entities/**/*.js"]`) |
|
||||
|
||||
#### Session Secret
|
||||
|
||||
@@ -133,11 +194,27 @@ Every single configuration option will be listed here
|
||||
|
||||
A Random string of characters (anything)
|
||||
|
||||
#### Port
|
||||
#### Meta Configuration
|
||||
|
||||
**Config Property:** `port`
|
||||
**Config Property:** `meta`
|
||||
|
||||
Port to run the webserver on
|
||||
Particles.JS, can be enabled and it's config can be changed willingly.
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
| --------------- | ------ | -------------------------------------------------------------------------------------------- |
|
||||
| `meta.favicon` | string | has to be in /public/assets folder and should be formatted as `"/public/assets/<file name>"` |
|
||||
| `meta.title` | string | title of your server shows up like `<title> - Login` or `<title> - Dashboard` |
|
||||
|
||||
#### Particles.JS Configuration
|
||||
|
||||
**Config Property:** `particles`
|
||||
|
||||
Particles.JS, can be enabled and it's config can be changed willingly.
|
||||
|
||||
| Config Property | Type | Description / Expected Values |
|
||||
| ------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `particles.enabled` | boolean | Whether particles should show up on routes |
|
||||
| `particles.config` | particles config | Config from [this](https://vincentgarreau.com/particles.js/) play around with the configuration, then paste the JSON to here |
|
||||
|
||||
### Example Config
|
||||
|
||||
@@ -148,35 +225,154 @@ Port to run the webserver on
|
||||
"tempDir": "./temp",
|
||||
"uploadDir": "./uploads"
|
||||
},
|
||||
"meta": {
|
||||
"favicon": "/public/assets/typex_small.png",
|
||||
"title": "TypeX"
|
||||
},
|
||||
"site": {
|
||||
"protocol": "http",
|
||||
"domain": "localhost:8000"
|
||||
"protocol": "https",
|
||||
"ssl": {
|
||||
"key": "./ssl/server.key",
|
||||
"cert": "./ssl/server.crt"
|
||||
},
|
||||
"serveHTTPS": 443, // https port to serve on (will be used if protocol is https)
|
||||
"serveHTTP": 8000 // http port to serve on (will be used if protocol is http)
|
||||
},
|
||||
"administrator": {
|
||||
"password": "1234",
|
||||
"authorization": "Administrator master"
|
||||
"authorization": "Administrator 1234"
|
||||
},
|
||||
"orm": {
|
||||
"type": "postgres",
|
||||
"host": "localhost",
|
||||
"port": 5432,
|
||||
"username": "postgres",
|
||||
"password": "password",
|
||||
"username": "user",
|
||||
"password": "1234",
|
||||
"database": "typex",
|
||||
"synchronize": true,
|
||||
"logging": false,
|
||||
"entities": [
|
||||
"out/src/entities/**/*.js"
|
||||
]
|
||||
"entities": ["out/src/entities/**/*.js"]
|
||||
},
|
||||
"sessionSecret": "aoshfyujfnbyurkjh53748uyfhn",
|
||||
"port": 8000
|
||||
"sessionSecret": "qwertyuiopasdfghjklzxcvbnm",
|
||||
"particles": {
|
||||
"enabled": true,
|
||||
"settings": {
|
||||
"particles": {
|
||||
"number": {
|
||||
"value": 52,
|
||||
"density": {
|
||||
"enable": true,
|
||||
"value_area": 800
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"value": "#cd4c4c"
|
||||
},
|
||||
"shape": {
|
||||
"type": "circle",
|
||||
"stroke": {
|
||||
"width": 0,
|
||||
"color": "#000000"
|
||||
},
|
||||
"polygon": {
|
||||
"nb_sides": 9
|
||||
},
|
||||
"image": {
|
||||
"src": "img/github.svg",
|
||||
"width": 60,
|
||||
"height": 100
|
||||
}
|
||||
},
|
||||
"opacity": {
|
||||
"value": 0.5,
|
||||
"random": false,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 1,
|
||||
"opacity_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"value": 0,
|
||||
"random": true,
|
||||
"anim": {
|
||||
"enable": false,
|
||||
"speed": 40,
|
||||
"size_min": 0.1,
|
||||
"sync": false
|
||||
}
|
||||
},
|
||||
"line_linked": {
|
||||
"enable": true,
|
||||
"distance": 150,
|
||||
"color": "#ffffff",
|
||||
"opacity": 0.4,
|
||||
"width": 1
|
||||
},
|
||||
"move": {
|
||||
"enable": true,
|
||||
"speed": 6,
|
||||
"direction": "none",
|
||||
"random": false,
|
||||
"straight": false,
|
||||
"out_mode": "out",
|
||||
"bounce": false,
|
||||
"attract": {
|
||||
"enable": false,
|
||||
"rotateX": 600,
|
||||
"rotateY": 1200
|
||||
}
|
||||
}
|
||||
},
|
||||
"interactivity": {
|
||||
"detect_on": "canvas",
|
||||
"events": {
|
||||
"onhover": {
|
||||
"enable": false,
|
||||
"mode": "grab"
|
||||
},
|
||||
"onclick": {
|
||||
"enable": false,
|
||||
"mode": "repulse"
|
||||
},
|
||||
"resize": true
|
||||
},
|
||||
"modes": {
|
||||
"grab": {
|
||||
"distance": 400,
|
||||
"line_linked": {
|
||||
"opacity": 1
|
||||
}
|
||||
},
|
||||
"bubble": {
|
||||
"distance": 400,
|
||||
"size": 40,
|
||||
"duration": 2,
|
||||
"opacity": 8,
|
||||
"speed": 3
|
||||
},
|
||||
"repulse": {
|
||||
"distance": 200,
|
||||
"duration": 0.4
|
||||
},
|
||||
"push": {
|
||||
"particles_nb": 4
|
||||
},
|
||||
"remove": {
|
||||
"particles_nb": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"retina_detect": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Compiling Typescript for running
|
||||
|
||||
Compile the Typescript code before running the code, or you can run it with `ts-node` which is not recommended. ***MAKE SURE YOU ARE IN THE PROJECT DIR!***
|
||||
Compile the Typescript code before running the code, or you can run it with `ts-node` which is not recommended. **_MAKE SURE YOU ARE IN THE PROJECT DIR!_**
|
||||
|
||||
```sh
|
||||
tsc -p .
|
||||
|
||||
55
package-lock.json
generated
55
package-lock.json
generated
@@ -54,6 +54,14 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cookie-parser": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.2.tgz",
|
||||
"integrity": "sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==",
|
||||
"requires": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz",
|
||||
@@ -228,7 +236,8 @@
|
||||
"buffer-writer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
|
||||
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
|
||||
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
|
||||
"dev": true
|
||||
},
|
||||
"busboy": {
|
||||
"version": "0.2.14",
|
||||
@@ -422,6 +431,15 @@
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||
},
|
||||
"cookie-parser": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz",
|
||||
"integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==",
|
||||
"requires": {
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6"
|
||||
}
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
@@ -884,7 +902,8 @@
|
||||
"packet-reader": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
|
||||
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
|
||||
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==",
|
||||
"dev": true
|
||||
},
|
||||
"parent-require": {
|
||||
"version": "1.0.0",
|
||||
@@ -928,6 +947,7 @@
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pg/-/pg-8.0.3.tgz",
|
||||
"integrity": "sha512-fvcNXn4o/iq4jKq15Ix/e58q3jPSmzOp6/8C3CaHoSR/bsxdg+1FXfDRePdtE/zBb3++TytvOrS1hNef3WC/Kg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-writer": "2.0.0",
|
||||
"packet-reader": "1.0.0",
|
||||
@@ -942,27 +962,32 @@
|
||||
"pg-connection-string": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz",
|
||||
"integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc="
|
||||
"integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=",
|
||||
"dev": true
|
||||
},
|
||||
"pg-int8": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
|
||||
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
|
||||
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
|
||||
"dev": true
|
||||
},
|
||||
"pg-pool": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.1.1.tgz",
|
||||
"integrity": "sha512-kYH6S0mcZF1TPg1F9boFee2JlCSm2oqnlR2Mz2Wgn1psQbEBNVeNTJCw2wCK48QsctwvGUzbxLMg/lYV6hL/3A=="
|
||||
"integrity": "sha512-kYH6S0mcZF1TPg1F9boFee2JlCSm2oqnlR2Mz2Wgn1psQbEBNVeNTJCw2wCK48QsctwvGUzbxLMg/lYV6hL/3A==",
|
||||
"dev": true
|
||||
},
|
||||
"pg-protocol": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.2.tgz",
|
||||
"integrity": "sha512-r8hGxHOk3ccMjjmhFJ/QOSVW5A+PP84TeRlEwB/cQ9Zu+bvtZg8Z59Cx3AMfVQc9S0Z+EG+HKhicF1W1GN5Eqg=="
|
||||
"integrity": "sha512-r8hGxHOk3ccMjjmhFJ/QOSVW5A+PP84TeRlEwB/cQ9Zu+bvtZg8Z59Cx3AMfVQc9S0Z+EG+HKhicF1W1GN5Eqg==",
|
||||
"dev": true
|
||||
},
|
||||
"pg-types": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
|
||||
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pg-int8": "1.0.1",
|
||||
"postgres-array": "~2.0.0",
|
||||
@@ -975,6 +1000,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz",
|
||||
"integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"split": "^1.0.0"
|
||||
}
|
||||
@@ -987,22 +1013,26 @@
|
||||
"postgres-array": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
|
||||
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
|
||||
"dev": true
|
||||
},
|
||||
"postgres-bytea": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
|
||||
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
|
||||
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=",
|
||||
"dev": true
|
||||
},
|
||||
"postgres-date": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz",
|
||||
"integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA=="
|
||||
"integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==",
|
||||
"dev": true
|
||||
},
|
||||
"postgres-interval": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
|
||||
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"xtend": "^4.0.0"
|
||||
}
|
||||
@@ -1091,7 +1121,8 @@
|
||||
"semver": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
|
||||
"integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
|
||||
"integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=",
|
||||
"dev": true
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
@@ -1159,6 +1190,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"through": "2"
|
||||
}
|
||||
@@ -1228,7 +1260,8 @@
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"dev": true
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
|
||||
10
package.json
10
package.json
@@ -1,22 +1,26 @@
|
||||
{
|
||||
"name": "typex",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"@ayanaware/logger": "^2.2.1",
|
||||
"@forevolve/bootstrap-dark": "^1.0.0-alpha.981",
|
||||
"@overnightjs/core": "^1.6.15",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/express-session": "^1.17.0",
|
||||
"@types/mime": "^2.0.1",
|
||||
"@types/multer": "^1.4.3",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"ejs": "^3.0.2",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.1",
|
||||
"http-status-codes": "^1.4.0",
|
||||
"mime": "^2.4.4",
|
||||
"multer": "^1.4.2",
|
||||
"pg": "^8.0.3",
|
||||
"typeorm": "^0.2.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"pg": "^8.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
public/assets/typex.png
Normal file
BIN
public/assets/typex.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
BIN
public/assets/typex_circle.png
Normal file
BIN
public/assets/typex_circle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 KiB |
BIN
public/assets/typex_small.png
Normal file
BIN
public/assets/typex_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
BIN
public/assets/typex_small_circle.png
Normal file
BIN
public/assets/typex_small_circle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
17
public/css/particles.css
Normal file
17
public/css/particles.css
Normal file
@@ -0,0 +1,17 @@
|
||||
canvas{
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
#particles-js canvas{
|
||||
position:absolute;
|
||||
z-index: -1;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background-image: url("");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: 50% 50%; }
|
||||
|
||||
|
||||
.count-particles{
|
||||
border-radius: 0 0 3px 3px;
|
||||
}
|
||||
1
public/js/particles.js
Normal file
1
public/js/particles.js
Normal file
@@ -0,0 +1 @@
|
||||
const startP = config => particlesJS("particles-js", JSON.parse(config));
|
||||
@@ -18,6 +18,7 @@ export class APIController {
|
||||
@Post('upload')
|
||||
@Middleware(upload.single('file'))
|
||||
private async upload(req: Request, res: Response) {
|
||||
if (req.headers['authorization'] === config.administrator.authorization) return res.status(BAD_REQUEST).json({ code: BAD_REQUEST, message: "You can't upload files with the administrator account." })
|
||||
if (req.headers['authorization'] !== (await this.orm.repos.user.find({ where: { token: req.headers['authorization'] } }))[0].token) return res.status(FORBIDDEN).json({ code: FORBIDDEN, message: "Unauthorized" })
|
||||
const user = (await this.orm.repos.user.find({ where: { token: req.headers['authorization'] } }))[0];
|
||||
const file = req.file;
|
||||
@@ -30,12 +31,13 @@ export class APIController {
|
||||
source.on("end", function () {
|
||||
unlinkSync(file.path);
|
||||
});
|
||||
getImage(this.orm, `${req.protocol}://${config.site.domain}/u/${id}.${extension}`, user.id)
|
||||
return res.status(200).send(`${req.protocol}://${config.site.domain}/u/${id}.${extension}`)
|
||||
getImage(this.orm, `${req.protocol}://${req.headers['host']}/u/${id}.${extension}`, user.id)
|
||||
return res.status(200).send(`${req.protocol}://${req.headers['host']}/u/${id}.${extension}`)
|
||||
}
|
||||
|
||||
@Post('user')
|
||||
private async newUser(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (!req.session.user) return res.status(FORBIDDEN).json({ code: FORBIDDEN, message: 'Unauthorized' });
|
||||
if (!req.session.user.administrator) return res.status(FORBIDDEN).json({ code: FORBIDDEN, message: 'Unauthorized' });
|
||||
const data = req.body;
|
||||
@@ -51,6 +53,7 @@ export class APIController {
|
||||
|
||||
@Patch('user')
|
||||
private async patchUser(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (!req.session.user) return res.status(FORBIDDEN).json({ code: FORBIDDEN, message: 'Unauthorized' });
|
||||
const data = req.body;
|
||||
try {
|
||||
@@ -65,6 +68,7 @@ export class APIController {
|
||||
|
||||
@Delete('user')
|
||||
private async deleteUser(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (!req.session.user) return res.status(FORBIDDEN).json({ code: FORBIDDEN, message: 'Unauthorized' });
|
||||
const q = req.query.user;
|
||||
try {
|
||||
|
||||
@@ -16,28 +16,53 @@ export class IndexController {
|
||||
|
||||
@Get('')
|
||||
private async index(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (!req.session.user) return res.redirect('/login');
|
||||
if (req.session.user && req.session.user.id !== 0) if (!(await this.orm.repos.user.findOne({ id: req.session.user.id }))) {
|
||||
res.clearCookie('typex_user');
|
||||
req.session.user = null;
|
||||
return res.redirect('/login')
|
||||
}
|
||||
const images = await this.orm.repos.image.find({ where: { user: req.session.user.id } });
|
||||
const users = await this.orm.repos.user.find({ order: { id: 'ASC' } });
|
||||
return res.render('index', { user: req.session.user, images, users })
|
||||
return res.render('index', { user: req.session.user, images, users, config })
|
||||
}
|
||||
|
||||
@Get('login')
|
||||
private async login(req: Request, res: Response) {
|
||||
if (req.session.user) return res.redirect('/')
|
||||
return res.status(200).render('login', { password: true, username: true })
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (req.session.user) return res.redirect('/');
|
||||
if (req.session.user && req.session.user.id !== 0) if (!(await this.orm.repos.user.findOne({ id: req.session.user.id }))) {
|
||||
res.clearCookie('typex_user');
|
||||
req.session.user = null;
|
||||
return res.redirect('/login')
|
||||
}
|
||||
return res.status(200).render('login', { password: true, username: true, config })
|
||||
}
|
||||
|
||||
@Get('logout')
|
||||
private async logout(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (!req.session.user) return res.redirect('/')
|
||||
if (req.session.user && req.session.user.id !== 0) if (!(await this.orm.repos.user.findOne({ id: req.session.user.id }))) {
|
||||
res.clearCookie('typex_user');
|
||||
req.session.user = null;
|
||||
return res.redirect('/login')
|
||||
}
|
||||
req.session.user = null;
|
||||
res.clearCookie('typex_user');
|
||||
res.redirect('/login');
|
||||
}
|
||||
|
||||
@Post('login')
|
||||
private async postLogin(req: Request, res: Response) {
|
||||
if (req.cookies.typex_user) req.session.user = req.cookies.typex_user;
|
||||
if (req.session.user) return res.redirect('/');
|
||||
if (req.session.user && req.session.user.id !== 0) if (!(await this.orm.repos.user.findOne({ id: req.session.user.id }))) {
|
||||
res.clearCookie('typex_user');
|
||||
req.session.user = null;
|
||||
return res.redirect('/login')
|
||||
}
|
||||
if (req.body.username == 'administrator' && req.body.password === config.administrator.password) {
|
||||
//@ts-ignore
|
||||
req.session.user = {
|
||||
@@ -47,12 +72,14 @@ export class IndexController {
|
||||
token: config.administrator.authorization,
|
||||
administrator: true
|
||||
}
|
||||
res.cookie('typex_user', req.session.user, { maxAge: 1036800000 });
|
||||
return res.redirect('/')
|
||||
}
|
||||
const user = await this.orm.repos.user.findOne({ where: { username: req.body.username } });
|
||||
if (!user) return res.status(200).render('login', { username: false, password: false })
|
||||
if (req.body.password !== user.password) return res.status(200).render('login', { password: false, username: false })
|
||||
req.session.user = user;
|
||||
res.cookie('typex_user', req.session.user, { maxAge: 1036800000 });
|
||||
return res.redirect('/')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { randomId } from "../util";
|
||||
import config from '../../config.json';
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@@ -22,7 +23,7 @@ export class User {
|
||||
this.username = options.username;
|
||||
this.password = options.password;
|
||||
this.administrator = options.administrator;
|
||||
this.token = randomId(32)
|
||||
this.token = randomId(config.user.randomIDSize)
|
||||
return this;
|
||||
}
|
||||
}
|
||||
26
src/index.ts
26
src/index.ts
@@ -1,8 +1,13 @@
|
||||
import './core/Console';
|
||||
import { Repository, Connection, createConnection, ConnectionOptions } from "typeorm";
|
||||
import "./core/Console";
|
||||
import {
|
||||
Repository,
|
||||
Connection,
|
||||
createConnection,
|
||||
ConnectionOptions,
|
||||
} from "typeorm";
|
||||
import { User } from "./entities/User";
|
||||
import { TypeXServer } from "./server";
|
||||
import config from '../config.json';
|
||||
import config from "../config.json";
|
||||
import Logger from "@ayanaware/logger";
|
||||
import { Image } from "./entities/Image";
|
||||
|
||||
@@ -17,15 +22,18 @@ export interface ORMHandler {
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const connection = await createConnection(config.orm as ConnectionOptions)
|
||||
const connection = await createConnection(config.orm as ConnectionOptions);
|
||||
const orm: ORMHandler = {
|
||||
connection,
|
||||
repos: {
|
||||
user: connection.getRepository(User),
|
||||
image: connection.getRepository(Image)
|
||||
}
|
||||
image: connection.getRepository(Image),
|
||||
},
|
||||
};
|
||||
if (orm.connection.isConnected) Logger.get(Connection).info(`Successfully initialized postgres`)
|
||||
if (orm.connection.isConnected)
|
||||
Logger.get(Connection).info(
|
||||
`Successfully initialized database type: ${config.orm.type}`
|
||||
);
|
||||
const server = new TypeXServer(orm);
|
||||
server.start(config.port)
|
||||
})();
|
||||
server.start();
|
||||
})();
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
import * as bodyParser from 'body-parser';
|
||||
import { Server } from '@overnightjs/core';
|
||||
import { Connection } from 'typeorm';
|
||||
import { ORMHandler } from '.';
|
||||
import Logger from '@ayanaware/logger';
|
||||
import config from '../config.json';
|
||||
import * as express from 'express';
|
||||
import session from 'express-session';
|
||||
import { APIController } from './controllers/APIController';
|
||||
import { IndexController } from './controllers/IndexController';
|
||||
import * as bodyParser from "body-parser";
|
||||
import { Server } from "@overnightjs/core";
|
||||
import { Connection } from "typeorm";
|
||||
import { ORMHandler } from ".";
|
||||
import Logger from "@ayanaware/logger";
|
||||
import config from "../config.json";
|
||||
import * as express from "express";
|
||||
import * as http from "http";
|
||||
import * as https from "https";
|
||||
import * as fs from "fs";
|
||||
import session from "express-session";
|
||||
import cookies from "cookie-parser";
|
||||
import { APIController } from "./controllers/APIController";
|
||||
import { IndexController } from "./controllers/IndexController";
|
||||
|
||||
export class TypeXServer extends Server {
|
||||
|
||||
constructor(orm: ORMHandler) {
|
||||
super();
|
||||
this.app.use(session({
|
||||
secret: config.sessionSecret,
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
}))
|
||||
this.app.set('view engine', 'ejs');
|
||||
this.app.use('/u', express.static('uploads'))
|
||||
this.app.use('/public', express.static('public'))
|
||||
this.app.use(
|
||||
session({
|
||||
secret: config.sessionSecret,
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
})
|
||||
);
|
||||
this.app.use(cookies());
|
||||
this.app.set("view engine", "ejs");
|
||||
this.app.use("/u", express.static("uploads"));
|
||||
this.app.use("/public", express.static("public"));
|
||||
this.app.use(bodyParser.json());
|
||||
this.app.use(bodyParser.urlencoded({ extended: true }));
|
||||
this.setupControllers(orm);
|
||||
@@ -32,9 +38,28 @@ export class TypeXServer extends Server {
|
||||
super.addControllers([index, api]);
|
||||
}
|
||||
|
||||
public start(port: number): void {
|
||||
this.app.listen(port, () => {
|
||||
Logger.get(TypeXServer).info('Started server on port ' + port);
|
||||
public start(): void {
|
||||
// this.app.listen(port, () => {
|
||||
// Logger.get(TypeXServer).info('Started server on port ' + port);
|
||||
// })
|
||||
let server;
|
||||
if (config.site.protocol === "https") {
|
||||
try {
|
||||
const creds = {
|
||||
key: fs.readFileSync(config.site.ssl.key, "utf-8"),
|
||||
cert: fs.readFileSync(config.site.ssl.cert, "utf-8")
|
||||
};
|
||||
server = https.createServer(creds, this.app);
|
||||
} catch (e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
Logger.get('TypeXServer.FS').error(`No file/directory found for ${e.path}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
} else server = http.createServer(this.app);
|
||||
|
||||
server.listen(config.site.protocol === 'https' ? config.site.serveHTTPS : config.site.serveHTTP, () => {
|
||||
Logger.get(TypeXServer).info('Started server on port ' + String(config.site.protocol === 'https' ? config.site.serveHTTPS : config.site.serveHTTP));
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@
|
||||
} */
|
||||
</style>
|
||||
<%- include('./partials/head') %>
|
||||
<title>TypeX</title>
|
||||
<title><%= config.meta.title %> - Dashboard</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="particles-js"></div>
|
||||
<div class="container h-100 d-flex justify-content-center">
|
||||
<div class="jumbotron my-auto">
|
||||
<ul class="nav nav-pills mb-3" id="main-view-tab-list" role="tablist">
|
||||
@@ -38,17 +39,16 @@
|
||||
</ul>
|
||||
<div class="tab-content" id="main-view">
|
||||
<div class="tab-pane fade show active m-3" id="home" role="tabpanel" aria-labelledby="home-tab">
|
||||
<h2>Welcome back, <%= user.username %></h2>
|
||||
<h2>Welcome back, <%= user.username %> <a class="btn btn-sm btn-danger" href="/logout"
|
||||
style="border-radius: 50px;">Logout</a>
|
||||
</h2>
|
||||
<p>You have <b><%= images.length %></b> images saved, and you
|
||||
<%= user.administrator ? 'are an administrator' : 'are not an administrator' %>. (<a
|
||||
href="/logout">Logout</a> from <%= user.username %>)</p>
|
||||
<%= user.administrator ? 'are an administrator' : 'are not an administrator' %>.</p>
|
||||
<h4>API Token</h4>
|
||||
<div class="btn-group" role="group" aria-label="API Token">
|
||||
<button type="button" class="btn btn-success" id="copyToken"
|
||||
style="border-top-left-radius: 50px; border-bottom-left-radius: 50px;">Copy</button>
|
||||
<button type="button" class="btn btn-danger" id="regenToken"
|
||||
style="border-top-right-radius: 50px; border-bottom-right-radius: 50px;">Regenerate</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-primary" id="copyToken"
|
||||
style="border-radius: 50px;">Copy</button>
|
||||
<button type="button" class="btn btn-sm btn-danger" id="regenToken"
|
||||
style="border-radius: 50px;">Regenerate</button>
|
||||
<h4 style="margin-top:12px">Update your Profile</h4>
|
||||
<form>
|
||||
<div class="form-group">
|
||||
@@ -109,7 +109,7 @@
|
||||
<% } %>
|
||||
<td>
|
||||
<% if (!u.administrator) { %>
|
||||
<button type="button" class="btn btn-danger"
|
||||
<button type="button" class="btn btn-sm btn-danger"
|
||||
style="border-radius: 50px;">Delete</button>
|
||||
<% } %>
|
||||
</td>
|
||||
@@ -117,7 +117,8 @@
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal">Create new
|
||||
<button style="border-radius: 50px;" type="button" class="btn btn-primary" data-toggle="modal"
|
||||
data-target="#modal">Create new
|
||||
User</button>
|
||||
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true">
|
||||
@@ -171,6 +172,20 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="display:none" id="partenabled"><%=config.particles.enabled%></p>
|
||||
<p style="display:none" id="part"><%=JSON.stringify(config.particles.settings) %></p>
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
|
||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
|
||||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
|
||||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/sweetalert2@9/dist/sweetalert2.min.js"></script>
|
||||
<script src="http://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
||||
<script>if (document.getElementById('partenabled').innerText === "true") particlesJS("particles-js", JSON.parse(document.getElementById('part').innerText));</script>
|
||||
<script>
|
||||
function whitespace(str) {
|
||||
return str === null || str.match(/^ *$/) !== null;
|
||||
|
||||
@@ -9,15 +9,11 @@
|
||||
}
|
||||
</style>
|
||||
<%- include('./partials/head') %>
|
||||
<title>TypeX - Login</title>
|
||||
<title><%= config.meta.title %> - Login</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<% if (!username) { %>
|
||||
<div style="display:none;" id="check">
|
||||
true
|
||||
</div>
|
||||
<% } %>
|
||||
<div id="particles-js"></div>
|
||||
<div class="container h-100 d-flex justify-content-center">
|
||||
<div class="jumbotron my-auto">
|
||||
<h1 class="display-4" style="text-align: center;">Login</h1>
|
||||
@@ -36,6 +32,20 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<p style="display:none" id="partenabled"><%=config.particles.enabled%></p>
|
||||
<p style="display:none" id="part"><%=JSON.stringify(config.particles.settings) %></p>
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
|
||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
|
||||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
|
||||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/sweetalert2@9/dist/sweetalert2.min.js"></script>
|
||||
<script src="http://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js"></script>
|
||||
<script>if (document.getElementById('partenabled').innerText === "true") particlesJS("particles-js", JSON.parse(document.getElementById('part').innerText));</script>
|
||||
<script>
|
||||
if (document.getElementById('check').value === 'true') {
|
||||
Swal.fire({
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="/public/css/bootstrap-dark.min.css" />
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
|
||||
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
|
||||
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
|
||||
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
|
||||
crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="/public/css/particles.css" />
|
||||
<link href="//cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@3/dark.css" rel="stylesheet">
|
||||
<script src="//cdn.jsdelivr.net/npm/sweetalert2@9/dist/sweetalert2.min.js"></script>
|
||||
<link rel="icon" href="<%=config.meta.favicon%>" type="image/png">
|
||||
Reference in New Issue
Block a user