Register and resend
This commit is contained in:
parent
32d2fa6059
commit
2f4b9fb1a3
43
handler.py
43
handler.py
@ -5,12 +5,18 @@
|
|||||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
# You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
|
||||||
from bottle import Bottle, route
|
from bottle import Bottle, route, request, response, redirect
|
||||||
from config import directory
|
from config import directory
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
import templates.plain.main as template_public
|
import templates.plain.main as template_public
|
||||||
|
import templates.postcard.main as template_email
|
||||||
|
|
||||||
import modules.public.home as public_home
|
import modules.public.home as public_home
|
||||||
|
|
||||||
|
import modules.api.auth as api_auth
|
||||||
|
|
||||||
app = Bottle()
|
app = Bottle()
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@ -21,3 +27,38 @@ def index():
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return public_home.main().html(params)
|
return public_home.main().html(params)
|
||||||
|
|
||||||
|
@app.route('/api/auth/registration/register/<roles>', method=['OPTIONS', 'POST'])
|
||||||
|
def index(roles):
|
||||||
|
try:
|
||||||
|
if request.method == 'OPTIONS':
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
response.content_type = 'application/json'
|
||||||
|
params = request.json
|
||||||
|
params["roles" ] = roles
|
||||||
|
params["mako" ] = {
|
||||||
|
"email" : template_email.main(directory.page["email"], "verification")
|
||||||
|
}
|
||||||
|
return json.dumps(api_auth.auth().register(params), indent = 2).encode()
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e),flush=True)
|
||||||
|
return json.dumps({}, indent = 2).encode()
|
||||||
|
|
||||||
|
@app.route('/api/auth/registration/resend', method='GET')
|
||||||
|
def index():
|
||||||
|
try:
|
||||||
|
if request.method == 'OPTIONS':
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
response.content_type = 'application/json'
|
||||||
|
params = {
|
||||||
|
"email" : request.query.email,
|
||||||
|
"mako" : {
|
||||||
|
"email" : template_email.main(directory.page["email"], "verification")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json.dumps(api_auth.auth().resend(params), indent = 2).encode()
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e),flush=True)
|
||||||
|
return json.dumps({}, indent = 2).encode()
|
||||||
|
136
modules/api/auth.py
Normal file
136
modules/api/auth.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import mysql.connector as mariadb
|
||||||
|
from mako.template import Template
|
||||||
|
from bottle import request
|
||||||
|
|
||||||
|
from config import database, globalvar
|
||||||
|
|
||||||
|
import bcrypt
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from scripts import loggorilla, saltedkey, googly, tokenguard, sendwave
|
||||||
|
|
||||||
|
import procedure.validation as procedure_validation
|
||||||
|
import procedure.webmail as procedure_webmail
|
||||||
|
|
||||||
|
class auth:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.db_main = mariadb.connect(**database.db_main)
|
||||||
|
self.cursor = self.db_main.cursor(dictionary=True)
|
||||||
|
self.smtpconfig = globalvar.smtpconfig
|
||||||
|
|
||||||
|
def register(self, params):
|
||||||
|
APIADDR = "/api/auth/registration/register/:roles"
|
||||||
|
loggorilla.prcss(APIADDR, "Define parameters")
|
||||||
|
response = {}
|
||||||
|
captcha = params["captcha" ]
|
||||||
|
username = params["username" ].lower()
|
||||||
|
email = params["email" ].lower()
|
||||||
|
password = params["password" ]
|
||||||
|
roles = params["roles" ]
|
||||||
|
self.cursor.execute("BEGIN;")
|
||||||
|
try:
|
||||||
|
loggorilla.prcss(APIADDR, "Get dependency data")
|
||||||
|
self.cursor.execute(f"SELECT id, name FROM `auth_roles` WHERE auth_roles.name = %s ; ", (roles,) )
|
||||||
|
result_roles = self.cursor.fetchone()
|
||||||
|
loggorilla.prcss(APIADDR, "Process parameters")
|
||||||
|
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
|
||||||
|
token = saltedkey.token(username, hashed)
|
||||||
|
if globalvar.production == True:
|
||||||
|
captcha_r = googly.recaptcha(captcha, globalvar.reCAPTCHA['server'])
|
||||||
|
score = captcha_r["score"]
|
||||||
|
else:
|
||||||
|
captcha_r = 'dev mode'
|
||||||
|
score = 0.9
|
||||||
|
loggorilla.fyinf(APIADDR, f'captcha_r : {captcha_r}')
|
||||||
|
loggorilla.fyinf(APIADDR, f'score : {score}')
|
||||||
|
|
||||||
|
loggorilla.prcss(APIADDR, "Validation")
|
||||||
|
result_validation = procedure_validation.validation().register(APIADDR, captcha, score, roles, username, password, email)
|
||||||
|
if result_validation['status'] == "valid":
|
||||||
|
loggorilla.prcss(APIADDR, "Inserting")
|
||||||
|
self.cursor.execute("INSERT INTO `auth` VALUES (%s, %s);", (token, hashed) )
|
||||||
|
self.cursor.execute("INSERT INTO `auth_profile` VALUES (DEFAULT, %s, %s, %s, NULL);", (token, username, email) )
|
||||||
|
auth_profile_lastrowid = self.cursor.lastrowid
|
||||||
|
self.cursor.execute("INSERT INTO `auth_profile_verification` VALUES (DEFAULT, %s, 'email', 0);", (auth_profile_lastrowid,) )
|
||||||
|
self.cursor.execute("INSERT INTO `auth_profile_roles` VALUES (DEFAULT, %s, %s);", (auth_profile_lastrowid, result_roles['id']) )
|
||||||
|
loggorilla.prcss(APIADDR, "Generate URL")
|
||||||
|
expired = globalvar.verification_link_expiration
|
||||||
|
expired_isoformat = expired.isoformat()
|
||||||
|
payload = {
|
||||||
|
"token" : token,
|
||||||
|
"expired": expired_isoformat
|
||||||
|
}
|
||||||
|
token_encrypt = tokenguard.encode(payload, globalvar.ssh['key']['private'], globalvar.ssh['passphrase'])
|
||||||
|
verification_url = globalvar.verification_url(token_encrypt)
|
||||||
|
notme_url = globalvar.notme_url(token_encrypt)
|
||||||
|
loggorilla.prcss(APIADDR, "Sending email")
|
||||||
|
webmail_data = {"verify": verification_url, "notme": notme_url}
|
||||||
|
result_webmail = procedure_webmail.webmail().verification(APIADDR, params, webmail_data)
|
||||||
|
self.smtpconfig['to' ] = email
|
||||||
|
self.smtpconfig['subject' ] = result_webmail['subject']
|
||||||
|
self.smtpconfig['text' ] = result_webmail['text' ]
|
||||||
|
self.smtpconfig['html' ] = result_webmail['html' ]
|
||||||
|
sendwave.smtp(self.smtpconfig)
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
response["status" ] = "success"
|
||||||
|
response["desc" ] = "Register success. Check email for verification."
|
||||||
|
response["data" ] = {
|
||||||
|
"recaptcha":captcha_r
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
response = result_validation
|
||||||
|
except Exception as e:
|
||||||
|
self.cursor.execute("ROLLBACK;")
|
||||||
|
loggorilla.error(APIADDR, str(e) )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "Internal Server Error. Please contact us if you still have an error."
|
||||||
|
finally:
|
||||||
|
self.cursor.execute("COMMIT;")
|
||||||
|
self.cursor.close()
|
||||||
|
self.db_main.close()
|
||||||
|
return response
|
||||||
|
|
||||||
|
def resend(self, params):
|
||||||
|
APIADDR = "/api/auth/registration/resend"
|
||||||
|
loggorilla.prcss(APIADDR, "Define parameters")
|
||||||
|
response = {}
|
||||||
|
email = params["email"].lower()
|
||||||
|
try:
|
||||||
|
loggorilla.prcss(APIADDR, "Get data for checking")
|
||||||
|
self.cursor.execute(f"SELECT COUNT(*) AS `count`, auth_profile.token, auth_profile.email FROM auth_profile_verification INNER JOIN auth_profile ON auth_profile.id = auth_profile_verification.profile WHERE auth_profile.email = %s AND auth_profile_verification.type = 'email' AND auth_profile_verification.verified = 0 ; ", (email,) )
|
||||||
|
result_unverified = self.cursor.fetchone()
|
||||||
|
token = result_unverified["token"].decode()
|
||||||
|
if result_unverified["count"] >= 1:
|
||||||
|
loggorilla.prcss(APIADDR, "Generate URL")
|
||||||
|
expired = globalvar.verification_link_expiration
|
||||||
|
expired_isoformat = expired.isoformat()
|
||||||
|
payload = {
|
||||||
|
"token" : token,
|
||||||
|
"expired": expired_isoformat
|
||||||
|
}
|
||||||
|
token_encrypt = tokenguard.encode(payload, globalvar.ssh['key']['private'], globalvar.ssh['passphrase'])
|
||||||
|
verification_url = globalvar.verification_url(token_encrypt)
|
||||||
|
notme_url = globalvar.notme_url(token_encrypt)
|
||||||
|
loggorilla.prcss(APIADDR, "Sending email")
|
||||||
|
webmail_data = {"verify": verification_url, "notme": notme_url}
|
||||||
|
result_webmail = procedure_webmail.webmail().verification(APIADDR, params, webmail_data)
|
||||||
|
self.smtpconfig['to' ] = email
|
||||||
|
self.smtpconfig['subject' ] = result_webmail['subject']
|
||||||
|
self.smtpconfig['text' ] = result_webmail['text' ]
|
||||||
|
self.smtpconfig['html' ] = result_webmail['html' ]
|
||||||
|
sendwave.smtp(self.smtpconfig)
|
||||||
|
loggorilla.prcss(APIADDR, "Giving response")
|
||||||
|
response["status" ] = "success"
|
||||||
|
response["desc" ] = "Resend success. Check email for verification."
|
||||||
|
else:
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "The parameters seems suspicious and you are not authorized for that"
|
||||||
|
except Exception as e:
|
||||||
|
loggorilla.error(APIADDR, str(e) )
|
||||||
|
response["status" ] = "failed"
|
||||||
|
response["desc" ] = "Internal Server Error. Please contact us if you still have an error. for detail"
|
||||||
|
finally:
|
||||||
|
self.cursor.close()
|
||||||
|
self.db_main.close()
|
||||||
|
return response
|
1
pages/email/message.html
Normal file
1
pages/email/message.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<p>${message}</p>
|
11
pages/email/verification.html
Normal file
11
pages/email/verification.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<h2>${header}</h2>
|
||||||
|
|
||||||
|
<p>Thanks for signing up! This is the start of an exciting journey and you’re just one step away from completing your account setup to start using your profile.</p>
|
||||||
|
<p>Click the button below to verify your account and get started.</p>
|
||||||
|
<a href="${verify}" class="button">
|
||||||
|
Verify email address
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<p>You are not registering this? <a href="${notme}">I'm not registering this</a></p>
|
||||||
|
<br>
|
11
scripts/googly.py
Normal file
11
scripts/googly.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
def recaptcha(captcha, secret):
|
||||||
|
url = "https://www.google.com/recaptcha/api/siteverify"
|
||||||
|
myobj = {
|
||||||
|
"secret" : secret,
|
||||||
|
"response" : captcha
|
||||||
|
}
|
||||||
|
response = json.loads(requests.post(url, data = myobj).text)
|
||||||
|
return response
|
13
scripts/loggorilla.py
Normal file
13
scripts/loggorilla.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
def prcss(loc, msg):
|
||||||
|
print(f"[loggorilla][{datetime.datetime.now()}][\033[32mprcss\033[39m][\033[95m{loc}\033[39m] {msg}", flush=True)
|
||||||
|
|
||||||
|
def accss(loc, msg):
|
||||||
|
print(f"[loggorilla][{datetime.datetime.now()}][\033[36maccss\033[39m][\033[95m{loc}\033[39m] {msg}", flush=True)
|
||||||
|
|
||||||
|
def fyinf(loc, msg):
|
||||||
|
print(f"[loggorilla][{datetime.datetime.now()}][\033[93mfyinf\033[39m][\033[95m{loc}\033[39m] {msg}", flush=True)
|
||||||
|
|
||||||
|
def error(loc, msg):
|
||||||
|
print(f"[loggorilla][{datetime.datetime.now()}][\033[31merror\033[39m][\033[95m{loc}\033[39m] {msg}", flush=True)
|
5
scripts/saltedkey.py
Normal file
5
scripts/saltedkey.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import bcrypt
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
def token(username, hashed):
|
||||||
|
return hashlib.sha1( (username+username[:3]+hashed[-6:]).encode() ).hexdigest()
|
23
scripts/sendwave.py
Normal file
23
scripts/sendwave.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
import smtplib
|
||||||
|
|
||||||
|
def smtp(config):
|
||||||
|
|
||||||
|
msg = MIMEMultipart('alternative')
|
||||||
|
msg['Subject' ] = config['subject' ]
|
||||||
|
msg['From' ] = config['from' ]
|
||||||
|
msg['To' ] = config['to' ]
|
||||||
|
|
||||||
|
part1 = MIMEText(config['text'], 'plain')
|
||||||
|
part2 = MIMEText(config['html'], 'html' )
|
||||||
|
|
||||||
|
msg.attach(part1)
|
||||||
|
msg.attach(part2)
|
||||||
|
|
||||||
|
smtp_server = smtplib.SMTP(config['server']['host'], config['server']['port'])
|
||||||
|
smtp_server.ehlo()
|
||||||
|
smtp_server.starttls()
|
||||||
|
smtp_server.login( config['login']['email'], config['login']['password'] )
|
||||||
|
smtp_server.sendmail('&&&&&&', config['to'], msg.as_string() )
|
||||||
|
smtp_server.quit()
|
23
scripts/tokenguard.py
Normal file
23
scripts/tokenguard.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from cryptography.hazmat.primitives import serialization
|
||||||
|
import jwt
|
||||||
|
|
||||||
|
def encode(payload, id_rsa, passphrase):
|
||||||
|
private_key = open(id_rsa, 'r').read()
|
||||||
|
key = serialization.load_ssh_private_key(private_key.encode(), password=passphrase)
|
||||||
|
token = jwt.encode(
|
||||||
|
payload = payload,
|
||||||
|
key = key,
|
||||||
|
algorithm = 'RS256'
|
||||||
|
)
|
||||||
|
return token
|
||||||
|
|
||||||
|
def decode(token, id_rsa):
|
||||||
|
public_key = open(id_rsa, 'r').read()
|
||||||
|
key = serialization.load_ssh_public_key(public_key.encode())
|
||||||
|
header = jwt.get_unverified_header(token)
|
||||||
|
payload = jwt.decode(
|
||||||
|
jwt = token,
|
||||||
|
key = key,
|
||||||
|
algorithms = [header['alg'], ]
|
||||||
|
)
|
||||||
|
return payload
|
Loading…
Reference in New Issue
Block a user