def search_diplomas(): """Method that search for diplomas of a student, given its cnp(student id). Firstly, it lists all the assets found in the blockchain, then it lists all the transactions of every asset. If the student cnp is found in any transaction and it was not revoked, the diploma is added to the response variable Args: stud_cnp (str): the id of the student. Returns: (html): the entity page (dict): response variable that contains all the valid diplomas with the corresponding asset name of the university that issued it. """ response = dict() response["diplomas"] = dict() stud_cnp = request.args.get("stud_cnp") assets = MultichainCLI.list_assets() burn_address = MultichainCLI.get_burn_address() for asset in assets: asset_transaction = MultichainCLI.list_assets_transactions( asset["name"]) for transaction in asset_transaction: if len(transaction["data"]) > 0: if stud_cnp == transaction["data"][0][0:4]: if burn_address not in transaction["addresses"]: response["diplomas"][transaction["data"][0] [4:]] = asset["name"] else: response["diplomas"].pop(transaction["data"][0][4:]) return render_template("entity.html", response=response)
def create_diploma_transaction(): """ Method that gives a diploma to a student. It gets the asset name of the university currency and sends a unit of that asset to the multisignature student+university. Then it creates a multisignature transfer from the multisignature student+university to university+high authority and signs it. It also adds the cnp(student id)+hash as metadata and adds the diploma to the database. Args: multisig_address (str): the multisignature of student+university. stud_cnp (str): the id of the student. diploma_hash (str): the hash of the diploma. diploma_name (str): the name of the diploma. Returns: (html): the university page. (dict): response variable that contains the students, diplomas and the hexblob of the transaction that the student must sign. """ response = dict() multisig_address = request.args.get("multisig_address") stud_cnp = request.args.get("stud_cnp") diploma_hash = request.args.get("diploma_hash") diploma_name = request.args.get("diploma_name") asset_name = MultichainCLI.get_asset_name() error = MultichainCLI.send_asset(multisig_address, asset_name) print("Student cnp: {}".format(stud_cnp)) if not error: time.sleep(0.5) asset_dest_addr = MultichainCLI.get_destination_addr_asset(asset_name) hexblob, errors = MultichainCLI.create_raw_trans(multisig_address, asset_dest_addr, asset_name, stud_cnp + diploma_hash) if errors: response["create_hexblob"] = "Multisignature with the high authority was not created. Please create the " \ "multisignature before issuing any diploma." else: response["create_hexblob"] = "Hexblob: {}".format(hexblob["hex"]) diploma = Diploma(hash=diploma_hash, name=diploma_name, student_cnp=stud_cnp) db.session.add(diploma) db.session.commit() students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response)
def create_university(): """ Method that creates a university. It gives a node activate, send and receive permissions, creates the multisignature and adds the university to the database. Args: univ_address (str): the address of the university. target_pubkey (str): the public key of the university. univ_name (str): the name of the university. asset_name (str): the asset name of the university. Returns: (html): the high authority page (dict): response variable that contains all the universities and whether there were errors at creation. """ response = dict() univ_address = request.args.get("univ_address") errors = MultichainCLI.create_university(univ_address) response['create_errors'] = "Could not create university" if errors else "" target_pubkey = request.args.get("target_pubkey").replace(" ", "") univ_name = request.args.get("univ_name") multisig_addr, errors = MultichainCLI.create_multisigaddress( session["pubkey"], target_pubkey) print(multisig_addr) if errors: response[ "create_errors"] = "Could not create multisignature address. The provided public key is not valid." else: asset_name = request.args.get("asset_name") univ_address = MultichainCLI.get_multisig_second_address( session["address"]) errors = MultichainCLI.issue_asset_univ(univ_address, asset_name, multisig_addr) if errors: response["create_errors"] = "Multisig was already created" else: db.session.add( University(name=univ_name, address=univ_address, pubkey=target_pubkey)) db.session.commit() universities = University.query.all() response["universities"] = universities_schema.dump( universities).data return render_template("high_authority.html", response=response)
def disconnect(): """ Method that disconnects a user from the application. It stops the blockchain. Returns: (html): the index page. """ MultichainCLI.disconeect() time.sleep(1) return render_template("index.html", response=dict())
def revoke_university(): """ Method that revokes a university. It revokes a node activate, send and receive permissions and deletes it from the database. Args: univ_address (str): the address of the university. Returns: (html): the high authority page (dict): response variable that contains all the universities and whether there were errors. """ response = dict() univ_address = request.args.get("univ_address") errors = MultichainCLI.revoke_university(univ_address) response['revoke_errors'] = "Could not revoke university" if errors else "" # carefull here! SQL injection possibility - must patch. db.session.execute( "delete from university where address = '{}'".format(univ_address)) db.session.commit() universities = University.query.all() response["universities"] = universities_schema.dump(universities).data return render_template("high_authority.html", response=response)
def revoke_student(): """ Method that revokes a student. It revokes send and receive permissions from a node and deletes the node to the database. Args: student address (str): the address of the student. Returns: (html): university page. (dict): response variable that contains all students and diplomas. """ response = dict() stud_address = request.args.get("stud_address") errors = MultichainCLI.revoke_stud(stud_address) response['revoke_errors'] = "Could not revoke student" if errors else "" # !SQL injection possibility - must patch. db.session.execute("delete from student where address = '{}'".format(stud_address)) db.session.commit() students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response)
def sign_transaction(): """ Method that sign a multisignature transaction blob and send the transaction to the destination. Args: transaction_blob (str): the transaction encoded in a hex blob. Returns: (html): student/high authority page, depending on node ranks. (dict): response variable that contains all the universities if the rank of the node is high authority. """ response = dict() transaction_blob = request.args.get("transaction_blob") _, errors = MultichainCLI.sign_and_send_transaction(transaction_blob) if session["rank"] == "student": if errors: response["sign_errors"] = "Could not sign the diploma transaction. You must create the multisignature with" \ " the university first." return render_template("student.html", response=response) if session["rank"] == "high_authority": universities = University.query.all() response["universities"] = universities_schema.dump(universities).data return render_template("high_authority.html", response=response)
def create_student(): """ Method that creates a student. It gives send and receive permissions to a node, creates a multisignature with the node and adds the node to the database. Args: student address (str): the address of the student. target_pubkey (str): the public key of the student. stud_name (str): the name of the student. stud_cnp (str): the id of the student. Returns: (html): university page (dict): response variable that contains all students and diplomas. """ response = dict() stud_address = request.args.get("stud_address") errors = MultichainCLI.create_stud(stud_address) response['create_errors'] = "Could not create student" if errors else "" target_pubkey = request.args.get("target_pubkey").replace(" ", "") stud_name = request.args.get("stud_name") stud_cnp = request.args.get("stud_cnp") if len(stud_cnp) != 4: response["create_errors"] = "CNP is invalid. It must contain 4 digits" else: multisig_addr, errors = MultichainCLI.create_multisigaddress(target_pubkey, session["pubkey"]) if errors: response["create_errors"] = "Could not create multisignature address. The provided public key is not valid." else: MultichainCLI.create_stud(multisig_addr) db.session.add(Student(cnp=stud_cnp, name=stud_name, address=stud_address, pubkey=target_pubkey, multisig=multisig_addr)) db.session.commit() students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response)
def create_univha_multisig(): response = dict() target_pubkey = request.args.get("target_pubkey").replace(" ", "") multisig_addr, errors = MultichainCLI.create_multisigaddress(target_pubkey, session["pubkey"]) if errors: response["multisig_errors"] = "Could not create multisignature address. The provided public key is not valid." else: MultichainCLI.grand_send_recieve(multisig_addr) students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response)
def verify_diploma(): """ Method that verifies if a diploma is valid. It lists all the transaction of the given asset and checks whether the cnp+diploma hash is found in the university+high authority multisignature address. It also checks if the diploma was revoked, the cnp+diploma was transferred to burn address. Args: diploma_hash (str): the hash of the diploma. asset_name (str): the name of the asset of the university. stud_cnp (str): the student id. Returns: (html): the entity page. (dict): response variable that contains a message that says whether the diploma is valid. """ response = dict() diploma_hash = request.args.get("diploma_hash") asset_name = request.args.get("asset_name") stud_cnp = request.args.get("stud_cnp") asset_transactions = MultichainCLI.list_assets_transactions(asset_name) burn_address = MultichainCLI.get_burn_address() diploma_hash_exists = False diploma_revoked = False for transaction in asset_transactions: if len(transaction["data"]) > 0: if stud_cnp + diploma_hash == transaction["data"][0]: if burn_address not in transaction["addresses"]: diploma_hash_exists = True else: diploma_revoked = True if diploma_hash_exists and not diploma_revoked: response["valid"] = "Diploma is valid" else: response["valid"] = "Diploma is not valid" return render_template("entity.html", response=response)
def revoke_diploma_transaction(): """ Method that revokes a diploma from a student. It creates a multisignature transfer from the multisignature between univ+high authority to the burn address. Args: stud_cnp (str): the id of the student. diploma_hash (str): the hash of the diploma. Returns: (html): the university page. (dict): response variable that contains the students, diplomas and the hexblob of the transaction that the high authority must sign. """ response = dict() stud_cnp = request.args.get("stud_cnp") diploma_hash = request.args.get("diploma_hash") asset_name = MultichainCLI.get_asset_name() asset_dest_addr = MultichainCLI.get_destination_addr_asset(asset_name) burn_address = MultichainCLI.get_burn_address() hexblob, _ = MultichainCLI.create_raw_trans(asset_dest_addr, burn_address, asset_name, stud_cnp + diploma_hash) response["revoke_hexblob"] = "Hexblob: {}".format(hexblob["hex"]) db.session.execute("delete from diploma where hash = '{}'".format(diploma_hash)) db.session.commit() students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response)
def create_studuniv_multisig(): """ Method that creates the multisignature with the university. Args: target_pubkey (str): the public key of the university. Returns: (html): student page. (dict): response variable that contains whether there was an error of creation of the multisignature. """ response = dict() target_pubkey = request.args.get("target_pubkey").replace(" ", "") _, errors = MultichainCLI.create_multisigaddress(session["pubkey"], target_pubkey) response["multisig_errors"] = "Could not create multisignature address. The provided public key is not valid." \ if errors else "" return render_template("student.html", response=response)
def connect(): """ Method that connects a user to the application. It stores the address, ip+port, public key and rank(student, university, high authority) in the session variable. Args: scholarium_address (str): the address(ip+port) of the node. Returns: (html): the page of student, university or high authority, depending on the rank of the node. (dict): response variable that contains students and diplomas for university, and universities for high authorities. """ response = dict() scholarium_address = request.args.get("scholarium_address") MultichainCLI.connect(scholarium_address) session["address"] = MultichainCLI.get_address() session['node_address'] = MultichainCLI.get_node_address() session["pubkey"] = MultichainCLI.get_node_public_key() session["rank"] = MultichainCLI.get_node_rank(session["address"]) if session["rank"] == "university": students = Student.query.all() response["students"] = students_schema.dump(students).data diplomas = Diploma.query.all() response["diplomas"] = diplomas_schema.dump(diplomas).data return render_template("university.html", response=response) if session["rank"] == "high_authority": universities = University.query.all() response["universities"] = universities_schema.dump(universities).data return render_template("high_authority.html", response=response) if session["rank"] == "student": return render_template("student.html", response=response) if session["rank"] == "entity": return render_template("entity.html", response=response)