From e6b46027e09d30b3d6a4613fc7bfbd0fcdfdca5b Mon Sep 17 00:00:00 2001 From: Pratyush Desai Date: Fri, 16 Jul 2021 16:39:58 +0530 Subject: [PATCH] Base code for registration --- .gitignore | 1 + flaskapp.py | 46 ++++++++++++++++++++++++ forms.py | 10 ++++++ irc_register.py | 78 ++++++++++++++++++++++++++++++++++++++-- templates/register.xhtml | 27 ++++++++++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 flaskapp.py create mode 100644 forms.py create mode 100644 templates/register.xhtml diff --git a/.gitignore b/.gitignore index bdaab25..b50d175 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ env/ +.env \ No newline at end of file diff --git a/flaskapp.py b/flaskapp.py new file mode 100644 index 0000000..a886164 --- /dev/null +++ b/flaskapp.py @@ -0,0 +1,46 @@ +from flask import Flask, render_template, url_for, request, redirect, flash +from forms import RegistrationForm +from irc_register import ircregister +import os + +app = Flask(__name__) + +# to prevent CSRF attacks +# KEEP SECRET +app.config["SECRET_KEY"] = os.getenv("FLASK_CSRF_SECRET_KEY") +webchat_url = os.getenv("WEBCHAT_URL") +home_url = os.getenv("HOME_URL") + +# getting the remote ip of user can be highly specific to your environment +# https://stackoverflow.com/questions/3759981/get-ip-address-of-visitors-using-flask-for-python + +user_ip = request.environ.get("HTTP_X_REAL_IP", request.remote_addr) + +@app.route("/register", methods=["GET", "POST"]) +def register(): + form = RegistrationForm() + if request.method == "POST": + userip = user_ip + username = request.form.get("username") + password = request.form.get("password") + + response = ircregister(userip, username, password) + if response == "disconnected": + flash("Server Unavailable") + elif response == "WebIRC bad password": + flash("Bad Config. Please contact server administrators") + elif response == "ERR_ERRONEUSNICKNAME": # shouldn't happen if sanitized in the form + flash("Illegal Character in Username. Please choose a different one one.") + elif response == "ERR_NICKNAMEINUSE": + flash("Username already taken. Please choose a different one!") + elif response == "SUCCESS": + return redirect(webchat_url) + else: + return redirect(home_url) + elif request.method == "GET": + return render_template('register.xhtml', title='Register', form=form) + + + +if __name__ == '__main__': + app.run(debug=True) \ No newline at end of file diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..ea052af --- /dev/null +++ b/forms.py @@ -0,0 +1,10 @@ +from flask_wtf import FlaskForm +from wtforms import StringField, PasswordField, SubmitField +from wtforms.validators import DataRequired, Length, EqualTo + + +class RegistrationForm(FlaskForm): + username = StringField('Username', validators=[DataRequired(), Length(min=1, max=32)]) + password = PasswordField('Password', validators=[DataRequired()]) + confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')]) + submit = SubmitField('Register') \ No newline at end of file diff --git a/irc_register.py b/irc_register.py index f83284c..824081a 100644 --- a/irc_register.py +++ b/irc_register.py @@ -1,4 +1,76 @@ -import irctokens, socket +import irctokens +import socket +import os -def ircregister(userip, webircpass, username, password, email): - pass \ No newline at end of file +webircpass = os.getenv("WEBIRC_PASS") + +def ircregister(userip, username, password, email="*"): + + d = irctokens.StatefulDecoder() + e = irctokens.StatefulEncoder() + s = socket.socket() + + # Here we assume using this only on localhost i.e. loopback + s.connect(("127.0.0.1", 6667)) + + # define the send function + def _send(line): + print(f"> {line.format()}") + e.push(line) + while e.pending(): + e.pop(s.send(e.pending())) + + # Registering connection + + # WEBIRC + _send(irctokens.build("WEBIRC", [ webircpass, "WebregGateway", userip, userip, "secure"])) + + # Check for "ERROR :Invalid WebIRC password" + # Should all of this this be under a try except block? + lines = d.push(s.recv(1024)) + if lines == None: + print("!disconnected") + return "disconnected" + elif lines.command == "ERROR" and lines.params == "Invalid WebIRC password": + return "WebIRC bad password" + + # Inform the server that we support + # CAP 3.2 + _send(irctokens.build("CAP", ["LS", "302"])) + + # REGISTER can be attempted before-connect if server supports + # but if the server responds with the corresponding FAIL we + # need to try again. We can also handle email-required using + # the same keys. How to access these key-value pairs? + # reference: https://github.com/ProgVal/ircv3-specifications/blob/register/extensions/account-registration.md#commands + + # NICK and USER + _send(irctokens.build("USER", ["u", "0", "*", username])) + _send(irctokens.build("NICK", [username])) + + # go through all cases + + while True: + for line in lines: + print(f"< {line.format()}") + if line.command == "432": + return "ERR_ERRONEUSNICKNAME" + elif line.command == "433": + return "ERR_NICKNAMEINUSE" + _send(irctokens.build("CAP", ["REQ", "draft/account-registration"])) + if line.command == "CAP" and line.params == ["*", "NAK", "draft/account-registration"]: + return "cap refused" + elif line.command == "CAP" and line.params == ["*", "ACK", "draft/account-registration"]: + to_send = irctokens.build("CAP", ["END"]) + _send(to_send) + if line.command == "PING": + to_send = irctokens.build("PONG", [line.params[0]]) + _send(to_send) + if line.command == "001": + # assuming no verif reqd. + to_send = irctokens.build("REGISTER", ["*", email, password]) + _send(to_send) + if line.command == "REGISTER" and ("SUCCESS" in line.params): + to_send = irctokens.build("QUIT") + _send(to_send) + return "SUCCESS" \ No newline at end of file diff --git a/templates/register.xhtml b/templates/register.xhtml new file mode 100644 index 0000000..4678bea --- /dev/null +++ b/templates/register.xhtml @@ -0,0 +1,27 @@ + + + + + + Register + + + {% for message in get_flashed_messages() %} + {{ message }} + {% endfor %} +
+ {{ form.hidden_tag() }} +
+ Sign Up + {{ form.username.label }} + {{ form.username }} + {{ form.password.label }} + {{ form.password }} + {{ form.confirm_password.label }} + {{ form.confirm_password }} +
+ {{ form.submit }} +
+ + \ No newline at end of file