<gh_stars>0
from flask import Flask, request, render_template, make_response, redirect, url_for
from flask_restful import Resource, Api
from flask_jwt import JWT, jwt_required
from security import authenticate, Indentity
from models import User, Message
from flask_socketio import SocketIO
from threading import Lock
import secrets
#comment this if tables are already created
#import table

#configurations
mutex=Lock()
app = Flask( __name__,static_url_path='/static')
api = Api(app)
app.secret_key='<KEY>' #generated using python secrets module
public = '-----<KEY>'
private='-----<KEY>-----END RSA PRIVATE KEY-----\r\n'
socketio = SocketIO(app)


#variables used to keep track of user data

session_mapping={}                                                                                                      #keeps track of websocket sessions
logged_in=[]                                                                                                            #keeps track of logged_in users
key_mapping={}                                                                                                          #maps 16 byte tokens to userids


jwt=JWT(app,authenticate, Indentity)                                                                                    #initialises jwt function
                                                                                                                        # /auth is the endpoint for jwt authorisation


#api for registeration
class Register(Resource):
    def get(self):                                                                                                      #returns registeration.html file on get request
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('registeration.html'),200,headers)

    def post(self):                                                                                                     #inserts data from the submitted form into user table
        data = request.get_json();

        username=User.find_by_username(data['username'])                                                                #to check if username already exists
        if(username==None):
            u=User.insert_user(data['username'], data['email'], data['password'], data['publickey'], data['privatekey'])
            #print(data['publickey'],"\n\n", data['privatekey'], "\n\n", data['password'] )
            return {"messege" : "success", "username":data['username']};
        else:
            return {"messege": "username already exists"};

#api for login
class Login(Resource):
    def get(self):                                                                                                      #returns login.html file on get request
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('login.html'), 200, headers)

    def post(self):                                                                                                     #performs authentication
        data = request.get_json();
        print(data)
        x=authenticate(data['username'],data['password'])
        if(x!=None):
            print(x.id)
            state=0

            mutex.acquire()
            if x.id in logged_in:
                state=1
            else:
                logged_in.append(x.id)                                                                                  #inserts userid into logged_in variable
                key_mapping[x.id]=secrets.token_hex(16)                                                                 #initialises 16byte hex token and maps it to userid
            mutex.release()

            if state==0:
                return {"user_id" : x.id, "key" : key_mapping[x.id]};                                                   #returns userid and key values user for AES encryption(the key is the password) on client side
            else:
                return {"already_logged_in" : "True"};
        else:
            pass

#api for homepage which displays all registered usernames
class homepage(Resource):
    def get(self, name):                                                                                                #returns homepage.html
        print(name)
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('homepage.html'), 200, headers)

    @jwt_required()                                                                                                     #decorator for jtw authentication
    def post(self, name):                                                                                               #returns all usernames
        print(name)
        u=User.return_all_users()
        return {"names":u}


class chat(Resource):
    def get(self, name, name1):                                                                                         #returns chat_room.html
        print(name)
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('chat_room.html'), 200, headers)

    @jwt_required()
    def post(self, name, name1):                                                                                        #check if jwt token is valid or not
        return {"authenticated":"True"}


class logout_force(Resource):
    def get(self):
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('logout_force.html'), 200, headers)

    def post(self):
        data = request.get_json();
        username = authenticate(data['username'],data['password'])
        if(username!=None):
            mutex.acquire()
            i=username.id
            if i in logged_in:
                logged_in.remove(i)  # removes username from logged_in list
            mutex.release()

            key_mapping[i] = "None"  # removex 16 byte hex token created

            return {"message" : "successful"}
        else:
            return {"message" : "invalid username or password"}


@app.route("/")
def red():                                                                                                              #redirects user from / to /login
    return redirect(url_for('login'))


@app.route("/logout/<name>")
def logout(name):                                                                                                       #performs logout operations
    i=int(name)

    mutex.acquire()
    if i in logged_in:
        logged_in.remove(i)                                                                                             #removes username from logged_in list
    mutex.release()

    key_mapping[int(name)]="None"                                                                                       #removex 16 byte hex token created

    return render_template('logout.html')                                                                               #this html file erases the user password stored on client side


#socket control
#api to establish socket connection and retreive ECDH keys
@socketio.on('connect_user')
def create_connection(json):                                                                                            #establishes socket connection and receives userid and recipientid
    print('connected')


    session_mapping[json['userid']]=request.sid                                                                         #maps userid to session id
    print(session_mapping)
    text_hist=Message.find_by_userids(json['userid'], json['recipientid'])                                              #retreives text history between user and recipient

    user=User.return_pub_pri_keys(json['userid'])                                                                       #retreives user public and private keys
    recipient=User.return_pub_pri_keys(json['recipientid'])                                                             #retreives recipient public key

    json['recipient_publickey']=recipient[0]                                                                            #recipient[0] contains public key   recipient=[publickey, privatekey]
    json['user_publickey']=user[0]
    json['user_privatekey']=user[1]
    json['text_hist']=text_hist
    json['you'] = User.find_by_id(json['userid']).username                                                              #retreives username
    #json['key'] = key_mapping[int(json['userid'])]

    if int(json['userid']) in key_mapping.keys():                                                                       #checks if key is there in the key_mapping
        json['key'] = key_mapping[int(json['userid'])]
    else:
        json['key'] = "None"

    print(json['key'])
    json['mapping']={json['userid'] : json['you'], json['recipientid']:User.find_by_id(json['recipientid']).username}   #maps username to userid

    print(json)
    socketio.emit('connect_return', json, room=request.sid)

#api to route text to appropriate destination
@socketio.on('sending_text')
def send_and_receive_text(json, methods=['GET', 'POST']):
    receiver_session_id = json['recipientid']

    print(str(json))

    user_name_1=User.find_by_id(json['userid']).username                                                                #find user and receivers userids
    recipient_name=User.find_by_id(json['recipientid']).username

    Message.insert_message(json['userid'], json['recipientid'], json['message'])                                        #insert message into database to store it

    if(receiver_session_id not in session_mapping):
        json['username'] = user_name_1
        print(json)
        socketio.emit('text_response', json, room=request.sid)
    else:
        receiver_session_id = session_mapping[json['recipientid']]
        print(user_name_1, recipient_name)
        json['username'] = user_name_1
        json['recipient'] = recipient_name
        #print(json)
        socketio.emit('text_response', json, room=receiver_session_id)                                                  #sends data back to both user and receiver
        socketio.emit('text_response', json, room=request.sid)                                                          #data contains username and encrypted message




api.add_resource(Register, '/register')
api.add_resource(Login, '/login')
api.add_resource(logout_force, '/logout')
api.add_resource(homepage,'/homepage/<name>')
api.add_resource(chat,'/homepage/<name>/<name1>')


if __name__ == '__main__':
    socketio.run(app, port=80)


from flask import Flask, request, render_template, make_response, redirect, url_for
from flask_restful import Resource, Api
from flask_jwt import JWT, jwt_required
from security import authenticate, Indentity
from models import User, Message
from flask_socketio import SocketIO
from threading import Lock
import secrets
#comment this if tables are already created
#import table

#configurations
mutex=Lock()
app = Flask( __name__,static_url_path='/static')
api = Api(app)
app.secret_key='<KEY>' #generated using python secrets module
public = '-----<KEY>'
private='-----<KEY>-----END RSA PRIVATE KEY-----\r\n'
socketio = SocketIO(app)


#variables used to keep track of user data

session_mapping={}                                                                                                      #keeps track of websocket sessions
logged_in=[]                                                                                                            #keeps track of logged_in users
key_mapping={}                                                                                                          #maps 16 byte tokens to userids


jwt=JWT(app,authenticate, Indentity)                                                                                    #initialises jwt function
                                                                                                                        # /auth is the endpoint for jwt authorisation


#api for registeration
class Register(Resource):
    def get(self):                                                                                                      #returns registeration.html file on get request
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('registeration.html'),200,headers)

    def post(self):                                                                                                     #inserts data from the submitted form into user table
        data = request.get_json();

        username=User.find_by_username(data['username'])                                                                #to check if username already exists
        if(username==None):
            u=User.insert_user(data['username'], data['email'], data['password'], data['publickey'], data['privatekey'])
            #print(data['publickey'],"\n\n", data['privatekey'], "\n\n", data['password'] )
            return {"messege" : "success", "username":data['username']};
        else:
            return {"messege": "username already exists"};

#api for login
class Login(Resource):
    def get(self):                                                                                                      #returns login.html file on get request
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('login.html'), 200, headers)

    def post(self):                                                                                                     #performs authentication
        data = request.get_json();
        print(data)
        x=authenticate(data['username'],data['password'])
        if(x!=None):
            print(x.id)
            state=0

            mutex.acquire()
            if x.id in logged_in:
                state=1
            else:
                logged_in.append(x.id)                                                                                  #inserts userid into logged_in variable
                key_mapping[x.id]=secrets.token_hex(16)                                                                 #initialises 16byte hex token and maps it to userid
            mutex.release()

            if state==0:
                return {"user_id" : x.id, "key" : key_mapping[x.id]};                                                   #returns userid and key values user for AES encryption(the key is the password) on client side
            else:
                return {"already_logged_in" : "True"};
        else:
            pass

#api for homepage which displays all registered usernames
class homepage(Resource):
    def get(self, name):                                                                                                #returns homepage.html
        print(name)
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('homepage.html'), 200, headers)

    @jwt_required()                                                                                                     #decorator for jtw authentication
    def post(self, name):                                                                                               #returns all usernames
        print(name)
        u=User.return_all_users()
        return {"names":u}


class chat(Resource):
    def get(self, name, name1):                                                                                         #returns chat_room.html
        print(name)
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('chat_room.html'), 200, headers)

    @jwt_required()
    def post(self, name, name1):                                                                                        #check if jwt token is valid or not
        return {"authenticated":"True"}


class logout_force(Resource):
    def get(self):
        headers = {'Content-Type': 'text/html'}
        return make_response(render_template('logout_force.html'), 200, headers)

    def post(self):
        data = request.get_json();
        username = authenticate(data['username'],data['password'])
        if(username!=None):
            mutex.acquire()
            i=username.id
            if i in logged_in:
                logged_in.remove(i)  # removes username from logged_in list
            mutex.release()

            key_mapping[i] = "None"  # removex 16 byte hex token created

            return {"message" : "successful"}
        else:
            return {"message" : "invalid username or password"}


@app.route("/")
def red():                                                                                                              #redirects user from / to /login
    return redirect(url_for('login'))


@app.route("/logout/<name>")
def logout(name):                                                                                                       #performs logout operations
    i=int(name)

    mutex.acquire()
    if i in logged_in:
        logged_in.remove(i)                                                                                             #removes username from logged_in list
    mutex.release()

    key_mapping[int(name)]="None"                                                                                       #removex 16 byte hex token created

    return render_template('logout.html')                                                                               #this html file erases the user password stored on client side


#socket control
#api to establish socket connection and retreive ECDH keys
@socketio.on('connect_user')
def create_connection(json):                                                                                            #establishes socket connection and receives userid and recipientid
    print('connected')


    session_mapping[json['userid']]=request.sid                                                                         #maps userid to session id
    print(session_mapping)
    text_hist=Message.find_by_userids(json['userid'], json['recipientid'])                                              #retreives text history between user and recipient

    user=User.return_pub_pri_keys(json['userid'])                                                                       #retreives user public and private keys
    recipient=User.return_pub_pri_keys(json['recipientid'])                                                             #retreives recipient public key

    json['recipient_publickey']=recipient[0]                                                                            #recipient[0] contains public key   recipient=[publickey, privatekey]
    json['user_publickey']=user[0]
    json['user_privatekey']=user[1]
    json['text_hist']=text_hist
    json['you'] = User.find_by_id(json['userid']).username                                                              #retreives username
    #json['key'] = key_mapping[int(json['userid'])]

    if int(json['userid']) in key_mapping.keys():                                                                       #checks if key is there in the key_mapping
        json['key'] = key_mapping[int(json['userid'])]
    else:
        json['key'] = "None"

    print(json['key'])
    json['mapping']={json['userid'] : json['you'], json['recipientid']:User.find_by_id(json['recipientid']).username}   #maps username to userid

    print(json)
    socketio.emit('connect_return', json, room=request.sid)

#api to route text to appropriate destination
@socketio.on('sending_text')
def send_and_receive_text(json, methods=['GET', 'POST']):
    receiver_session_id = json['recipientid']

    print(str(json))

    user_name_1=User.find_by_id(json['userid']).username                                                                #find user and receivers userids
    recipient_name=User.find_by_id(json['recipientid']).username

    Message.insert_message(json['userid'], json['recipientid'], json['message'])                                        #insert message into database to store it

    if(receiver_session_id not in session_mapping):
        json['username'] = user_name_1
        print(json)
        socketio.emit('text_response', json, room=request.sid)
    else:
        receiver_session_id = session_mapping[json['recipientid']]
        print(user_name_1, recipient_name)
        json['username'] = user_name_1
        json['recipient'] = recipient_name
        #print(json)
        socketio.emit('text_response', json, room=receiver_session_id)                                                  #sends data back to both user and receiver
        socketio.emit('text_response', json, room=request.sid)                                                          #data contains username and encrypted message




api.add_resource(Register, '/register')
api.add_resource(Login, '/login')
api.add_resource(logout_force, '/logout')
api.add_resource(homepage,'/homepage/<name>')
api.add_resource(chat,'/homepage/<name>/<name1>')


if __name__ == '__main__':
    socketio.run(app, port=80)
#comment this if tables are already created #import table #configurations #generated using python secrets module #variables used to keep track of user data #keeps track of websocket sessions #keeps track of logged_in users #maps 16 byte tokens to userids #initialises jwt function # /auth is the endpoint for jwt authorisation #api for registeration #returns registeration.html file on get request #inserts data from the submitted form into user table #to check if username already exists #print(data['publickey'],"\n\n", data['privatekey'], "\n\n", data['password'] ) #api for login #returns login.html file on get request #performs authentication #inserts userid into logged_in variable #initialises 16byte hex token and maps it to userid #returns userid and key values user for AES encryption(the key is the password) on client side #api for homepage which displays all registered usernames #returns homepage.html #decorator for jtw authentication #returns all usernames #returns chat_room.html #check if jwt token is valid or not # removes username from logged_in list # removex 16 byte hex token created #redirects user from / to /login #performs logout operations #removes username from logged_in list #removex 16 byte hex token created #this html file erases the user password stored on client side #socket control #api to establish socket connection and retreive ECDH keys #establishes socket connection and receives userid and recipientid #maps userid to session id #retreives text history between user and recipient #retreives user public and private keys #retreives recipient public key #recipient[0] contains public key   recipient=[publickey, privatekey] #retreives username #json['key'] = key_mapping[int(json['userid'])] #checks if key is there in the key_mapping #maps username to userid #api to route text to appropriate destination #find user and receivers userids #insert message into database to store it #print(json) #sends data back to both user and receiver #data contains username and encrypted message