Implementing Checkout Times for Attendees on Open Event Server

As of this writing, Open Event Server did not have the functionality to add, manipulate and delete checkout times of attendees. Event organizers should have access to log and update attendee checkout times. So it was decided to implement this functionality in the server. This boiled down to having an additional attribute checkout_times in the ticket holder model of the server. So the first step was to add a string column named checkout_times in the ticket holder database model, since this was going to be a place for comma-separated values (CSV) of attendee checkout times. An additional boolean attribute named is_checked_out was also added to convey whether an attendee has checked out or not. After the addition of these attributes in the model, we saved the file and performed the required database migration: To create the migration file for the above changes: $ python manage.py db migrate To upgrade the database instance: $ python manage.py db upgrade Once the migration was done, the API schema file was modified accordingly: class AttendeeSchemaPublic(SoftDeletionSchema): """ Api schema for Ticket Holder Model """ … checkout_times = fields.Str(allow_none=True) # ← is_checked_out = fields.Boolean() # ← … After the schema change, the attendees API file had to have code to incorporate these new fields. The way it works is that when we receive an update request on the server, we add the current time in the checkout times CSV to indicate a checkout time, so the checkout times field is essentially read-only: from datetime import datetime ... class AttendeeDetail(ResourceDetail): def before_update_object(self, obj, data, kwargs): … if 'is_checked_out' in data and data['is_checked_out']: ... else: if obj.checkout_times and data['checkout_times'] not in \ obj.checkout_times.split(","): data['checkout_times'] = '{},{},{}'.format( obj.checkout_times, data['checkout_times'], datetime.utcnow())   This completes the implementation of checkout times, so now organizers can process attendee checkouts on the server with ease. Resources SQLAlchemy Docs: https://docs.sqlalchemy.org/en/latest/ Alembic Docs: http://alembic.zzzcomputing.com/en/latest/

Continue ReadingImplementing Checkout Times for Attendees on Open Event Server

Migrating Event Ratings of Open Event with Stored Procedures

Many developers know about procedural languages and have used them in some form or another, but this is really an unpopular tool, despite its power. There are many advantages (and few disadvantages) of these languages, which we will learn about soon. Having a right amount of database-stored procedure code with the help of these languages can really enhance the speed and responsiveness of an application. This article will teach us how procedural languages can be utilized in database management and how they were used recently for a bug fix in Open Event Server. PostgreSQL, like any other powerful, relational database management system (RDBMS), provides the functionality to create and use stored procedures. Essentially, a stored procedure is database logic code which is saved on the database server. This code can be executed directly in the database, and can (and is!) often used to shift business logic from the application layer of a software to the database layer. This simple shift often has many advantages - including faster execution (as code executes at a lower stack level) and better security. When firing database queries from the application layer (i.e., the code that programmers write for storing programmable objects, performing business logic and so on), it often happens that parameters from the programming language itself are passed in to SQL, which then generates a complete SQL query. For example, here’s how a novice query might look like: import psycopg2 conn = psycopg2.connect(dbname="oevent", user="john", password="start") cur = conn.cursor() name = "Sam" cur.execute("SELECT * FROM users WHERE name='%s'" % name) # DANGEROUS! This is an extremely “exposed” code that can be exploited for malicious access, with a technique called SQL injection. This technique essentially “injects” malicious code via these passed parameters, like the variable name mentioned in the above code. With having stored procedures for business logic, there is no room for SQL injection. They solve this problem by writing the query beforehand, and having the parameterized data as a different entity. The pre-processed query within the corresponding stored procedure now looks like SELECT * FROM users WHERE name=?   The database driver sends the name of this stored procedure (or, in standard parameterised queries, just the query text itself) and a list of parameters, as distinct separate entities in the protocol. More details on how stored procedures enhance security can be found here. After learning so much about the advantages of stored procedures (which are enabled by procedural languages), let’s write one! Postgres supports multiple languages for writing stored procedures; here we will use PL/pgSQL, which is the most popular choice for Postgres. This procedural language, inspired (heavily) by Oracle’s PL/SQL language, looks very similar to SQL. To use this procedural language, we have to first install it. In Postgres, procedural languages are installed per-database, not server-wide. We can use the popular Postgres client psql for this purpose, or simply the createlang command on the command line: $ createlang plpgsql yourdb   Now let’s create a simple procedure that prints the corresponding grades…

Continue ReadingMigrating Event Ratings of Open Event with Stored Procedures

Implementing Event Average Rating with SQLAlchemy

While implementing Open Event Server version 2, we decided to have a better way of ranking events by their quality. To define the “quality” of events, the programmers decided to accumulate the feedbacks of specific events and take the average of the ratings involved. Thus, the average rating of an event proves to be a good (enough) measure of its quality. While there are many ways to implement aggregate relationships in an app, here I demonstrate a rather modern methodology which insists on storing such aggregates once they’re computed. Since there is always a space-time/computation tradeoff in software development, this task was no exception. At first, the straightforward idea that came to my mind was to query the Postgres database every time a request for average rating was made. This sounds simple, but with hundreds of events stored on a server, and potentially thousands of users querying for events, this seemed to be a computationally expensive approach. It was costly because the average rating aggregate would be computed for each request, and there could potentially be thousands of such concurrent requests. Therefore, a better idea is to compute the aggregate once, store it in the database (compromising space in the tradeoff mentioned above, but saving a large amount of computation at the same time), and update only when a change is made. In our specific case, the update should happen only when a new rating is added, a rating is deleted or an existing rating is modified. Since the advantages outnumbered the disadvantages, this was the strategy to be implemented. The first step in implementing average rating was to modify the database model of events accordingly. For this, I performed the necessary imports in the events’ database model file: from sqlalchemy_utils import aggregated from app.models.feedback import Feedback Now comes the tricky part. We want an average_rating column in the events table, that contains the mean rating of events. The values in this column should be updated every time a change is made to the feedbacks table. To perform this sort of functionality, the best, raw tool is a Postgres trigger. A trigger should be created that is fired after every update to the feedbacks table, which should update the average rating values in the events table. Here’s how the raw code of such a trigger looks like: create or replace function UpdateAverageRating() returns trigger AS $$ BEGIN UPDATE events SET average_rating=( SELECT avg(rating) FROM feedbacks WHERE event_id=NEW.event_id GROUP BY event_id ) WHERE id = NEW.event_id END $$ language plpgsql Fortunately, the translation of such a trigger into SQLAlchemy-speak is not only easy, but also very elegant. The imports I showed above already set the context for this translation. The event model class looks like the following: class Event(db.Model): """Event object table""" __tablename__ = 'events' __versioned__ = { 'exclude': ['schedule_published_on', 'created_at'] } id = db.Column(db.Integer, primary_key=True) identifier = db.Column(db.String) name = db.Column(db.String, nullable=False) external_event_url = db.Column(db.String) … … … The list of attributes continues, and to the end of this list,…

Continue ReadingImplementing Event Average Rating with SQLAlchemy

Implementing Badgename Update Functionality

Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python. Badgeyay has many features related to enhancement in generation of badges. It gives choice of uploading data entries i.e by CSV or manually. There are options available for choosing Badge Background and font specifications. Now the next important thing from User perspective is that there should be a feature in My badges panel where user can see all badges & other details  and should be able to edit them if he want to, so moving forward with this feature I have implemented Badge Name update functionality in the frontend. In this blog, I will be discussing how I implemented Update Badge Name functionality in my Pull Request so that the User can change his Badge Name  at any point of time in my badges panel. Let’s get started and understand it step by step. Step 1: Create Badge Name component with Ember CLI. $ ember g component badge-name   Step 2: Make changes in Handlebar of Badge Name. We will be using semantic UI form for making the changes in Handlebars. <form class="ui form" {{action 'updateBadgeName' on="change"}}> class="ui icon input"> class="pen square icon"> {{input type="text" value=badge.badge_name }} </form>   We have used action on submitting the Form for changing and updating the Badgename in Database. Step 3: We will now define the action in badge name JS file. We will also add the validations in Form so that empty form cannot be submitted to the server. import Component from '@ember/component'; import Ember from 'ember'; const { inject } = Ember; export default Component.extend({ init() { this._super(...arguments); }, notifications : inject.service('notification-messages'), actions : { updateBadgeName() { this.get('sendBadgeName')(this.get('badge')); }, didRender() { this.$('.ui.form') .form({ inline : true, delay : false, fields : { Name: { identifier : 'Name', rules : [ { type : 'empty', prompt : 'Please enter a valid Badge Name' } ] } } }); } } });   Step 4: We will now configure the controller to customize the action that we have defined above. import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; export default Controller.extend({ routing : service('-routing'), notifications : service('notification-messages'), actions : { updateBadgeName(badge) { badge.save() .then(() => this.get('notifications').success('Badge Name Successfully Updated!', { autoClear : true, clearDuration : 1500 })); } } });   Now, I am done with doing all the changes in Frontend. Step 6: Now run the Frontend & Backend to see the implemented changes. My Badges Panel Resources: Ember Docs -  Link Badgeyay Repository - Link Issue Link - Link Pull Request Link - Link Semantic UI -  LInk  

Continue ReadingImplementing Badgename Update Functionality

Implementing Different Alignment for Different Line

Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python. Badgeyay comes with many features for customising the process of generation of Badges. Now to provide more freedom to the user in generation of badges, I have worked on feature which will provide user more freedom in choosing different text alignment  for different lines and create badges more creatively. In this Blog, I will be discussing how I implemented different text alignment for Different Line in Badgeyay Backend in my Pull Request. To implement different text alignment for Different Line feature,  first, the component in SVG that is determining the text alignment of the label has to be identified. The label that determines the text on the badge is the <text> label and within it, the label that determines the properties of the text is <tspan>. So mainly we need to alter the properties in the tspan. The property that determines the font type for the badge is text-align and its default value is set to start(right alignment). If the property in the labels changed, then we can see the corresponding changes in the PDF generated from the svg. Now the challenges were: To Determine the text-align value from the frontend. Using the same for the text-align in SVG.. Changing the built SVG accordingly. In this Blog, I will be dealing with changing the SVG in Backend according to text-align property provided by the User in the Frontend. def change_text_align(self, filename, badge_size, paper_size, align_1, // Values from Frontend align_2, align_3, align_4, align_5): """ Module to change Text Alignment of each badge line :param `filename` - svg file to modify. :param `align_1` - Text Alignment to be applied on first line :param `align_2` - Text Alignment to be applied on Second line :param `align_3` - Text Alignment to be applied on Third line :param `align_4` - Text Alignment to be applied on Fourth line :param `align_5` - Text Alignment to be applied on Fifth line """ // Storing the Values passed altogether in a list. align = [1, align_1, align_2, align_3, align_4, align_5] // Selecting the dimension config based on the parameters passed in the function. dimensions = badge_config[paper_size][badge_size] if config.ENV == 'LOCAL': filename = 'static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' else: filename = os.getcwd() + '/api/static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' tree = etree.parse(open(os.path.join(self.APP_ROOT, filename), 'r')) element = tree.getroot() for idx in range(1, dimensions.badges + 1): for row in range(1, 6): //Selecting the text element with the ID _id = 'Person_color_{}_{}'.format(idx, row) path = element.xpath(("//*[@id='{}']").format(_id))[0] style_detail = path.get("style") style_detail = style_detail.split(";") for ind, i in enumerate(style_detail): if i.split(':')[0] == 'text-align': style_detail[ind] = "text-align:" + align[row] style_detail = ';'.join(style_detail) text_nodes = path.getchildren() path.set("text-align", style_detail) for t in text_nodes: text_style_detail = t.get("style") text_style_detail = text_style_detail.split(";") // Fill the text-align argument of the selected object by changing the value of text-align. text_style_detail[-1] = "text-align:" + align[row] text_style_detail = ";".join(text_style_detail) t.set("style", text_style_detail) etree.ElementTree(element).write(filename, pretty_print=True) print("Text Alignment Saved!")   After…

Continue ReadingImplementing Different Alignment for Different Line

Implementing Different Font Type for Different Line

Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python. Badgeyay comes with many features for customising the process of generation of Badges. Now to provide more freedom to the user in generation of badges, I have worked on feature which will provide user more freedom in choosing font types for different lines and create badges more creatively. In this Blog, I will be discussing how I implemented Different Font types for Different Line in Badgeyay Backend in my Pull Request. To implement Different Font type for Different Line feature,  first, the component in SVG that is determining the font of the label has to be identified. The label that determines the text on the badge is the <text> label and within it, the label that determines the properties of the text is <tspan>. So mainly we need to alter the properties in the tspan. The property that determines the font type for the badge is font-family and its default value is set to sans-serif. If the property in the labels changed, then we can see the corresponding changes in the PDF generated from the svg. Now the challenges were: To Determine the font-type value from the frontend. Using the same for the font-type in SVG.. Changing the built SVG accordingly. In this Blog, I will be dealing with changing the SVG in Backend according to Font type provided by the User in the Frontend. def change_font_family(self, filename, badge_size, paper_size, Font_1, // Values from Frontend Font_2, font_3, font_4, font_5): """ Module to change Font Family of each badge lines :param `filename` - svg file to modify. :param `font_1` - Family to be applied on first line :param `font_2` - Family to be applied on Second line :param `font_3` - Family to be applied on Third line :param `font_4` - Family to be applied on Fourth line :param `font_5` - Family to be applied on Fifth line """ // Storing the Values passed altogether in a list. font = [1, font_1, font_2, font_3, font_4, font_5] // Selecting the dimension config based on the parameters passed in the function. dimensions = badge_config[paper_size][badge_size] if config.ENV == 'LOCAL': filename = 'static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' else: filename = os.getcwd() + '/api/static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' tree = etree.parse(open(os.path.join(self.APP_ROOT, filename), 'r')) element = tree.getroot() for idx in range(1, dimensions.badges + 1): for row in range(1, 6): //Selecting the text element with the ID _id = 'Person_color_{}_{}'.format(idx, row) path = element.xpath(("//*[@id='{}']").format(_id))[0] style_detail = path.get("style") style_detail = style_detail.split(";") for ind, i in enumerate(style_detail): if i.split(':')[0] == 'font-family': style_detail[ind] = "font-family:" + font[row] style_detail = ';'.join(style_detail) text_nodes = path.getchildren() path.set("font-family", style_detail) for t in text_nodes: text_style_detail = t.get("style") text_style_detail = text_style_detail.split(";") // Fill the font family argument of the selected object by changing the value of font-family. text_style_detail[-1] = "font-family:" + font[row] text_style_detail = ";".join(text_style_detail) t.set("style", text_style_detail) etree.ElementTree(element).write(filename, pretty_print=True) print("Font Family Saved!")   After all the changes, the Updated SVG is…

Continue ReadingImplementing Different Font Type for Different Line

Implementing Different Font Size for Different Line

Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python. Badgeyay comes with many features for customising the process of generation of Badges. Now to provide more freedom to the user in generation of badges, I have worked on feature which will provide user more freedom in choosing font sizes for different lines and create badges more creatively. In this Blog, I will be discussing how I implemented Different Font Size for Different Line in Badgeyay Backend in my Pull Request. To implement Different Font Size for Different Line feature,  first, the component in SVG that is determining the font size of the label has to be identified. The label that determines the text on the badge is the <text> label and within it, the label that determines the properties of the text is <tspan>. So mainly we need to alter the properties in the tspan. The property that determines the font size for the badge is font-size and its default value is set to 31.25 px. If the property in the labels changed, then we can see the corresponding changes in the PDF generated from the svg. Now the challenges were: To Determine the font-size value from the frontend. Using the same for the font-size in SVG.. Changing the built SVG accordingly. In this Blog, I will be dealing with changing the SVG in Backend according to Font Size provided by the User in the Frontend. def change_font_size(self, filename, badge_size, paper_size, Font_size_1, // Values from Frontend font_size_2, font_size_3, font_size_4, font_size_5): """ Module to change size of each badge lines :param `filename` - svg file to modify. :param `font_size_1` - Size to be applied on first line :param `font_size_2` - Size to be applied on Second line :param `font_size_3` - Size to be applied on Third line :param `font_size_4` - Size to be applied on Fourth line :param `font_size_5` - Size to be applied on Fifth line """ // Storing the Values passed altogether in a list. font_size = [1, font_size_1, font_size_2, font_size_3, font_size_4, font_size_5] // Selecting the dimension config based on the parameters passed in the function. dimensions = badge_config[paper_size][badge_size] if config.ENV == 'LOCAL': filename = 'static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' else: filename = os.getcwd() + '/api/static/badges/' + dimensions.badgeSize + 'on' + dimensions.paperSize + '.svg' tree = etree.parse(open(os.path.join(self.APP_ROOT, filename), 'r')) element = tree.getroot() for idx in range(1, dimensions.badges + 1): for row in range(1, 6): //Selecting the text element with the ID _id = 'Person_color_{}_{}'.format(idx, row) path = element.xpath(("//*[@id='{}']").format(_id))[0] style_detail = path.get("style") style_detail = style_detail.split(";") for ind, i in enumerate(style_detail): if i.split(':')[0] == 'font-size': style_detail[ind] = "font-size:" + font_size[row] style_detail = ';'.join(style_detail) text_nodes = path.getchildren() path.set("font-size", style_detail) for t in text_nodes: text_style_detail = t.get("style") text_style_detail = text_style_detail.split(";") // Fill the font size argument of the selected object by changing the value of font-size. text_style_detail[-1] = "font-size:" + font_size[row] text_style_detail = ";".join(text_style_detail) t.set("style", text_style_detail) etree.ElementTree(element).write(filename, pretty_print=True) print("Font Size Saved!")     After all the changes, the Updated…

Continue ReadingImplementing Different Font Size for Different Line

Implementing Password Update Functionality

The Badgeyay  Ember JS frontend has many features like Login and Sign up features and Login with OAuth and most important, the badge generation feature is also up and running. Now the next important thing from User perspective is that there should be a settings panel where user can see its account details like username, Email & password and he should be able to change them if he want to. I have implemented the setting panel in Badgeyay where user can see his account details. In this blog, I will be discussing how I implemented Update Password functionality in my Pull Request so that the User can change his Password at any point of time. Let’s get started and understand it step by step. Step 1: Generate User Password component with help of ember cli. Step 2: Make changes in Handlebar of User Password. We will be using semantic UI form for making the changes in Handlebars. <h2 class="ui header">Password</h2> <h5 class="ui dividing header">Change your password.</h5> <form class="ui form" {{action 'updateUserPassword' on="submit"}}> class="field"> New Password class="fields"> class="ten wide field"> {{input type="password" id="newPassword" name=newPassword value=user.password}} </div> </div> class="field"> Verify Password class="fields"> class="ten wide field"> {{input type="password" id="newPasswordVerify" name=newPasswordVerify placeholder="Re-enter Password"}} </div> </div> <button type="submit" class="ui basic orange button" tabindex="0"> Save Changes </button> </form>   We have used action on submitting the Form for changing and updating the Password in Database and Firebase. Step 3: We will now define the action in user component JS file. We will also add the validations in Form so that empty form cannot be submitted to the server. import Component from '@ember/component'; export default Component.extend({ init() { this._super(...arguments); }, actions: { updateUserPassword() { let password = this.get('newPassword'); this.get('sendUserPassword')(password); } }, didRender() { this.$('.ui.form') .form({ inline : true, delay : false, fields : { newPassword: { identifier : 'newPassword', rules : [ { type : 'empty', prompt : 'Please enter a password' }, { type : 'minLength[6]', prompt : 'Your password must have at least {ruleValue} characters' } ] }, newPasswordVerify: { identifier : 'newPasswordVerify', rules : [ { type : 'match[newPassword]', prompt : 'Passwords do not match' } ] } } }); } });   Step 4: We will now configure the controller to customize the action that we have defined above. ....... export default Controller.extend({ routing : service('-routing'), notify : service('notify'), uid : '', actions : { ............... updateUserPassword() { this.get('user').save() .then(() => this.get('notify').success('Password Successfully Updated!')) } } });   Step 5: We have configured the frontend for sending the details to backend. Now, we have to edit the endpoint so that if Password changes in params, It should change the password and send the response with the updated user schema. api/controllers/registerUser.py ............... if 'password' in data.keys(): user.password = data['password'] update_firebase_password(user.id, user.password) user.save_to_db()   Now, I am done with doing all the changes in backend API and Frontend. Step 6: Now run the Frontend & Backend to see the implemented changes. User password Panel Now, we are done with implementation of Update password Functionality. Resources:…

Continue ReadingImplementing Password Update Functionality

Implementing User-name Update Functionality

The Badgeyay  Ember JS frontend has many features like Login and Sign up features and Login with OAuth and the most important, the badge generation feature is also up and running. Now the next important thing from User perspective is that there should be a settings panel where user can see its account details like username, Email & password and he should be able to change them if he want to. I have implemented the setting panel in Badgeyay where user can see his account details. In this blog, I will be discussing how I implemented Update Username functionality in my Pull Request so that the User can change his username at any point of time. Let’s get started and understand it step by step. Step 1: Generate User account component with help of ember cli. $ ember g component user-component/user-account   Step 2: Make changes in Handlebar of User Account. We will be using semantic UI form for making the changes in Handlebars. // user-account.hbs <h2 class="ui dividing header">Account</h2> <form class="ui form" {{action 'updateUserName' on="submit"}}> class="ui field"> Username class="ui fields"> class="ten wide field"> {{input type="text" id="profileName" name=profileName value=user.username}} </div> </div> class="ui field"> Email class="ui fields"> class="ten wide disabled field"> {{input type="email" name=email value=user.email}} </div> </div> <button type="submit" class="ui basic orange button" tabindex="0" >Save Changes</button> </form>   We have used action on submitting the Form for changing and updating the username in Database and Firebase. Step 3: We will now define the action in user component JS file. We will also add the validations in Form so that empty form cannot be submitted to the server. import Component from '@ember/component'; export default Component.extend({ init() { this._super(...arguments); }, actions: { updateUserName() { let profileName = this.get('profileName'); this.get('sendUserName')(profileName); } }, didRender() { this.$('.ui.form') .form({ inline : true, delay : false, fields : { username: { identifier : 'profileName', rules : [ { type : 'empty', prompt : 'Please enter a valid username' } ] } } }); }});   Step 4: We will now configure the controller to customize the action that we have defined above. ……. export default Controller.extend({ routing : service('-routing'), notify : service('notify'), uid : '', actions : { …………... updateUserName(profileName) { const _this = this; const user = this.get('store').peekAll('user'); user.forEach(user_ => { _this.set('uid', user_.get('id')); }); _this.get('user').save(); _this.get('notify').success('Username Successfully Updated!'); } } });   Step 5: We have configured the frontend for sending the details to backend. Now, we have to edit the endpoint so that if username is change in params, It should change the username and send the response with the updated username. api/controllers/registerUser.py …………... if 'username' in data.keys(): user.username = data['username'] update_firebase_username(user.id, user.username) user.save_to_db()   Now, I am done with doing all the changes in backend API and Frontend. Step 6: Now run the Frontend & Backend to see the implemented changes. User Account Panel Now, we are done with implementation of Update Username Functionality. Resources: Ember Docs -  Link Badgeyay Repository - Link Issue Link - Link Pull Request Link - Link Semantic UI -…

Continue ReadingImplementing User-name Update Functionality

Forgot Password Service in Badgeyay

Badgeyay is an open source badge generator service for generating badges developed by FOSSASIA community for technical events and conferences. The project is divided into two components mainly frontend and backend. After creating the user registration functionality in application, if the user forgets the credentials for the login, then there must be a way to recreate the credentials using a secure channel. This is only valid for the users signed up through email login as for the case of OAuth they must have access to their ID on respective social platform. The main challenges in resetting password for the user is to provide a secure channel. So the problem can be breakdown into following issues: Creating a token for reset action Sending that token via mail to user Verifying that token on the server and giving access Changing the credentials  of the user Procedure Generating token for the request to change credentials for the user. The token will be an expiry token and will be expired in the mentioned duration. So the token is valid for only a limited period of time and will prevent fraudulent requests. def pwd_reset_token():   data = request.get_json()['data']['attributes']   if 'email' not in data.keys():       print('Email not found')   email = data['email']   user = User.getUser(email=email)   if not user:       return ErrorResponse(UserNotFound().message, 422, {'Content-Type': 'application/json'}).respond()   expire = datetime.datetime.utcnow() + datetime.timedelta(seconds=900)   token = jwt.encode({       'id': user.id,       'exp': expire   }, app.config.get('SECRET_KEY'))   resetObj = ResetPasswordToken(user.id, token.decode('UTF-8'))   resetObj.save_to_db()   return jsonify(TokenSchema().dump(resetObj).data) Model for ResetPasswordToken class ResetPasswordToken(db.Model):   __tablename__ = 'Reset Password Token'   id = db.Column(db.String, primary_key=True)   token = db.Column(db.String, nullable=False)   def __init__(self, uid, token):       self.id = uid       self.token = token   def save_to_db(self):       try:           db.session.add(self)           db.session.commit()       except Exception as e:           db.session.rollback()           db.session.flush()           print(e)   Sending the password reset link via mail to the user. The link will contain the token (expiry token) that will be used to validate the request. For the case we will be using Firebase Cloud functions as an HTTP Trigger. exports.sendResetMail = functions.https.onRequest((req, res) => { let token = req.query['token']; let email = req.query['email']; res.setHeader('Content-Type', 'application/json'); sendResetMail(token, email)   .then(() => {     console.log('Reset mail sent to', email);     res.json({ data: { attributes: { status: 200 }, id: token, type: 'reset-mails' } });     return 0;   })   .catch(err => {     console.error(err);     res.json({ data: { attributes: { status: 500 }, id: token, type: 'reset-mails' } });     return -1;   }); }); function sendResetMail(token, email) { const mailOptions = {   from: `${APP_NAME}<noreply@firebase.com>`,   to: email, }; mailOptions.subject = `Password reset link`; mailOptions.html = '<p>Hey ' + email + '! Here is your password reset <a href=\'' + PASSWORD_RESET_LINK   + token + '\'>Link</a><p>'; return mailTransport.sendMail(mailOptions); }   Verifying the token on the server side to validate the user request def validate_reset_token():   args = request.args   if 'token' in args.keys():       token = args.get('token')   resp = {'id': token}   try:       jwt.decode(token, app.config['SECRET_KEY'])       resp['valid'] = True       return jsonify(ValidTokenSchema().dump(resp).data)   except Exception as e:       resp['valid'] = False       print(e)       return jsonify(ValidTokenSchema().dump(resp).data)   After user has access to change the credentials, then user can send a POST request to backend through a form shown in UI to change its password. def changePwd():…

Continue ReadingForgot Password Service in Badgeyay