Initial commit
This commit is contained in:
commit
ffa3b34739
5
.env.template
Normal file
5
.env.template
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Where is the GLAuth sqlite DB located?
|
||||
GLAUTH_DB=""
|
||||
|
||||
# Which port should the server run on?
|
||||
PORT=8080
|
134
.gitignore
vendored
Normal file
134
.gitignore
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
|
||||
captcha.png
|
||||
package-lock.json
|
62
README.md
Normal file
62
README.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
# qwik-register
|
||||
|
||||
## GLAuth installation
|
||||
|
||||
```
|
||||
git clone https://github.com/glauth/glauth.git
|
||||
cd glauth
|
||||
make fast
|
||||
make plugins
|
||||
```
|
||||
|
||||
## GLAuth config
|
||||
|
||||
```ini
|
||||
[ldap]
|
||||
enabled = true
|
||||
listen = "0.0.0.0:3893"
|
||||
|
||||
[ldaps]
|
||||
enabled = false
|
||||
listen = "0.0.0.0:3894"
|
||||
cert = "certs/server.crt"
|
||||
key = "certs/server.key"
|
||||
|
||||
[backend]
|
||||
datastore = "plugin"
|
||||
plugin = "sqlite.so"
|
||||
pluginhandler = "NewSQLiteHandler"
|
||||
baseDN = "dc=glauth,dc=com"
|
||||
database = "users.db"
|
||||
|
||||
nameformat = "cn"
|
||||
groupformat = "ou"
|
||||
```
|
||||
|
||||
## Pre database setup
|
||||
|
||||
```sql
|
||||
CREATE TABLE users (
|
||||
uidnumber INTEGER PRIMARY KEY autoincrement,
|
||||
id INTEGER,
|
||||
name TEXT NOT NULL,
|
||||
primarygroup INTEGER NOT NULL,
|
||||
othergroups TEXT DEFAULT '',
|
||||
givenname TEXT DEFAULT '',
|
||||
sn TEXT DEFAULT '',
|
||||
mail TEXT DEFAULT '',
|
||||
loginshell TYEXT DEFAULT '',
|
||||
homedirectory TEXT DEFAULT '',
|
||||
disabled SMALLINT DEFAULT 0,
|
||||
passsha256 TEXT DEFAULT '',
|
||||
passbcrypt TEXT DEFAULT '',
|
||||
otpsecret TEXT DEFAULT '',
|
||||
yubikey TEXT DEFAULT '',
|
||||
custattr TEXT DEFAULT '{}');
|
||||
|
||||
INSERT INTO groups(name, gidnumber) VALUES('users', 0);
|
||||
INSERT INTO groups(name, gidnumber) VALUES('admins', 10);
|
||||
INSERT INTO groups(name, gidnumber) VALUES('root', 100);
|
||||
|
||||
INSERT INTO includegroups(parentgroupid, includegroupid) VALUES(10, 0);
|
||||
```
|
93
captcha.sh
Executable file
93
captcha.sh
Executable file
|
@ -0,0 +1,93 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script is an example captcha script.
|
||||
# It takes the text to recognize in the captcha image as a parameter.
|
||||
# It return the image binary as a result. ejabberd support PNG, JPEG and GIF.
|
||||
|
||||
# The whole idea of the captcha script is to let server admins adapt it to
|
||||
# their own needs. The goal is to be able to make the captcha generation as
|
||||
# unique as possible, to make the captcha challenge difficult to bypass by
|
||||
# a bot.
|
||||
# Server admins are thus supposed to write and use their own captcha generators.
|
||||
|
||||
# This script relies on ImageMagick.
|
||||
# It is NOT compliant with ImageMagick forks like GraphicsMagick.
|
||||
|
||||
INPUT=$1
|
||||
|
||||
for n in $(od -A n -t u2 -N 48 /dev/urandom); do RL="$RL$n "; done
|
||||
get_random ()
|
||||
{
|
||||
R=${RL%% *}
|
||||
RL=${RL#* }
|
||||
}
|
||||
|
||||
get_random
|
||||
WAVE1_AMPLITUDE=$((2 + R % 5))
|
||||
get_random
|
||||
WAVE1_LENGTH=$((50 + R % 25))
|
||||
get_random
|
||||
WAVE2_AMPLITUDE=$((2 + R % 5))
|
||||
get_random
|
||||
WAVE2_LENGTH=$((50 + R % 25))
|
||||
get_random
|
||||
WAVE3_AMPLITUDE=$((2 + R % 5))
|
||||
get_random
|
||||
WAVE3_LENGTH=$((50 + R % 25))
|
||||
get_random
|
||||
W1_LINE_START_Y=$((10 + R % 40))
|
||||
get_random
|
||||
W1_LINE_STOP_Y=$((10 + R % 40))
|
||||
get_random
|
||||
W2_LINE_START_Y=$((10 + R % 40))
|
||||
get_random
|
||||
W2_LINE_STOP_Y=$((10 + R % 40))
|
||||
get_random
|
||||
W3_LINE_START_Y=$((10 + R % 40))
|
||||
get_random
|
||||
W3_LINE_STOP_Y=$((10 + R % 40))
|
||||
|
||||
get_random
|
||||
B1_LINE_START_Y=$((R % 40))
|
||||
get_random
|
||||
B1_LINE_STOP_Y=$((R % 40))
|
||||
get_random
|
||||
B2_LINE_START_Y=$((R % 40))
|
||||
get_random
|
||||
B2_LINE_STOP_Y=$((R % 40))
|
||||
#B3_LINE_START_Y=$((R % 40))
|
||||
#B3_LINE_STOP_Y=$((R % 40))
|
||||
|
||||
get_random
|
||||
B1_LINE_START_X=$((R % 20))
|
||||
get_random
|
||||
B1_LINE_STOP_X=$((100 + R % 40))
|
||||
get_random
|
||||
B2_LINE_START_X=$((R % 20))
|
||||
get_random
|
||||
B2_LINE_STOP_X=$((100 + R % 40))
|
||||
#B3_LINE_START_X=$((R % 20))
|
||||
#B3_LINE_STOP_X=$((100 + R % 40))
|
||||
|
||||
get_random
|
||||
ROLL_X=$((R % 40))
|
||||
|
||||
convert -size 180x60 xc:none -pointsize 40 \
|
||||
\( -clone 0 -fill white \
|
||||
-stroke black -strokewidth 4 -annotate +0+40 "$INPUT" \
|
||||
-stroke white -strokewidth 2 -annotate +0+40 "$INPUT" \
|
||||
-roll +$ROLL_X+0 \
|
||||
-wave "$WAVE1_AMPLITUDE"x"$WAVE1_LENGTH" \
|
||||
-roll -$ROLL_X+0 \) \
|
||||
\( -clone 0 -stroke black \
|
||||
-strokewidth 1 -draw \
|
||||
"line $B1_LINE_START_X,$B1_LINE_START_Y $B1_LINE_STOP_X,$B1_LINE_STOP_Y" \
|
||||
-strokewidth 1 -draw \
|
||||
"line $B2_LINE_START_X,$B2_LINE_START_Y $B2_LINE_STOP_X,$B2_LINE_STOP_Y" \
|
||||
-wave "$WAVE2_AMPLITUDE"x"$WAVE2_LENGTH" \) \
|
||||
\( -clone 0 -stroke white \
|
||||
-strokewidth 2 -draw "line 0,$W1_LINE_START_Y 140,$W1_LINE_STOP_Y" \
|
||||
-strokewidth 2 -draw "line 0,$W2_LINE_START_Y 140,$W2_LINE_STOP_Y" \
|
||||
-strokewidth 2 -draw "line 0,$W3_LINE_START_Y 140,$W3_LINE_STOP_Y" \
|
||||
-wave "$WAVE3_AMPLITUDE"x"$WAVE3_LENGTH" \) \
|
||||
-flatten -crop 140x60 +repage -quality 90 -depth 8 png:-
|
102
index.js
Normal file
102
index.js
Normal file
|
@ -0,0 +1,102 @@
|
|||
import Database from 'better-sqlite3'
|
||||
import express from 'express'
|
||||
import crypto from 'crypto'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
import { exec } from 'child_process'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
const app = express()
|
||||
const port = process.env.PORT
|
||||
let valid = {}
|
||||
let glauth = undefined
|
||||
|
||||
console.log(process.env)
|
||||
|
||||
dbInit()
|
||||
|
||||
app.use(express.urlencoded({
|
||||
extended: true
|
||||
}))
|
||||
|
||||
app.use(express.static('public'))
|
||||
|
||||
app.post('/register', (req, res) => {
|
||||
// Was input sent?
|
||||
if(!req.body.username)
|
||||
return(res.send("No username entered!"))
|
||||
|
||||
if(!req.body.password)
|
||||
return(res.send("No password entered!"))
|
||||
|
||||
if(!req.body.password)
|
||||
return(res.send("No captcha entered!"))
|
||||
|
||||
// does the username match the requirements
|
||||
if(!(/^(?=[a-zA-Z0-9]{2,20}$).*$/.test(req.body.username)))
|
||||
return(res.send("Username does not match the requirements"))
|
||||
|
||||
// is captcha valid
|
||||
if(!valid[req.body.captcha])
|
||||
return(res.send("Invalid captcha!"))
|
||||
|
||||
const captchaAge = Math.abs((valid[req.body.captcha].getTime() - new Date().getTime())/1000)
|
||||
|
||||
if(captchaAge > 600)
|
||||
return(res.send("Invalid captcha!"))
|
||||
|
||||
// expire the captcha
|
||||
delete valid[req.body.captcha]
|
||||
|
||||
// Does user already exist?
|
||||
if(glauth.prepare(`SELECT * FROM users WHERE name = ?`).get(req.body.username))
|
||||
return(res.send("User already exists"))
|
||||
|
||||
// Create the user!
|
||||
glauth.prepare(`
|
||||
INSERT INTO users(
|
||||
name, primarygroup, passsha256
|
||||
) VALUES(?, 0, ?)
|
||||
`).run(req.body.username, crypto.createHash('sha256').update(req.body.password).digest('hex'))
|
||||
|
||||
console.log(`>>> User: ${req.body.username} was succesfully created!`)
|
||||
res.send("Account registered!")
|
||||
|
||||
res.end()
|
||||
})
|
||||
|
||||
app.get('/captcha', async (req, res) => {
|
||||
const captcha = crypto.randomBytes(3).toString('hex')
|
||||
await execawait(`./captcha.sh ${captcha} > captcha.png`)
|
||||
|
||||
// Make it valid for 10 minutes
|
||||
valid[captcha] = new Date()
|
||||
|
||||
// Send the captcha image
|
||||
res.contentType('image/png');
|
||||
res.sendFile('captcha.png', {
|
||||
root: './'
|
||||
});
|
||||
})
|
||||
|
||||
app.listen(port);
|
||||
console.log('Server started at http://localhost:' + port);
|
||||
|
||||
|
||||
function execawait(cmd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
resolve(stdout ? stdout : stderr);
|
||||
});
|
||||
});7
|
||||
}
|
||||
|
||||
function dbInit() {
|
||||
glauth = new Database(process.env.GLAUTH_DB, {})
|
||||
|
||||
console.log(`Loaded in GLAuth - users.db`)
|
||||
}
|
18
package.json
Normal file
18
package.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "qwik-register",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^7.4.6",
|
||||
"dotenv": "^12.0.3",
|
||||
"express": "^4.17.2",
|
||||
"expresss": "^0.0.0"
|
||||
}
|
||||
}
|
17
public/index.html
Normal file
17
public/index.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<img src="./captcha">
|
||||
|
||||
<ul>
|
||||
<li>2-20 character in length</li>
|
||||
<li>only a-zA-Z0-9 characters only</li>
|
||||
</ul>
|
||||
<form method="POST" action="/register">
|
||||
<label for="username">Username:</label><br>
|
||||
<input type="text" id="username" name="username"><br>
|
||||
<label for="password">Password:</label><br>
|
||||
<input type="password" id="password" name="password">
|
||||
<br>
|
||||
<label for="captcha">Captcha:</label><br>
|
||||
<input type="text" id="captcha" name="captcha">
|
||||
<br>
|
||||
<input type="submit" value="Register!" />
|
||||
</form>
|
Loading…
Reference in New Issue
Block a user