Guest User

Untitled

a guest
Nov 16th, 2025
11
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.44 KB | None | 0 0
  1.  
  2. import secrets
  3. from datetime import datetime, timedelta
  4. from typing import Optional
  5.  
  6. from flask import flash
  7. from flask_login import UserMixin
  8. from flask_sqlalchemy import SQLAlchemy
  9. from itsdangerous.url_safe import URLSafeTimedSerializer
  10. from sqlalchemy import ForeignKey, Integer, String
  11. from sqlalchemy.orm import Mapped, mapped_column, relationship
  12.  
  13. from app.auth.models import User
  14.  
  15. db = SQLAlchemy()
  16.  
  17. # class/db in password reset token route
  18. class RouteToken(UserMixin, db.Model):
  19.     '''
  20.    One to One relationship between 1 table.
  21.    The One relationship is User and the other 1 relationship is route_token.
  22.    '''
  23.     # The difference between token and emailed_token is that token is used in a route and emailed_token is used in a form
  24.     id: Mapped[int] = mapped_column(primary_key=True)    
  25.     # Here is the token in the route like '.../rfjh9qoj#HH#F'
  26.     token: Mapped[Optional[str]] = mapped_column(String())  
  27.     # The columns below store the token from short 6 char token before inputted in the form
  28.     emailed_token: Mapped[Optional[str]] = mapped_column(String())    
  29.     time_token_expired: Mapped[Optional[datetime]] = mapped_column(index=True)
  30.     attempts_token_tried: Mapped[int] = mapped_column(Integer, default=0)    
  31.      # The "One" relationship/connection between the User table + FK.
  32.     fk_user_id: Mapped["int"] = mapped_column(ForeignKey('user.id'))
  33.     rel_user_routetoken: Mapped["User"] = relationship(back_populates='rel_route_token')
  34.  
  35.  
  36.     # The 3 methods below are added to the columns email_token + time_token_expired + attempts_token_tried in the User and RouteToken table.
  37.     # And the 3 methods are used in the function send_registration_token_email + send_password_reset_token_email that sends an email.
  38.    
  39.     # This method contains the token in the email
  40.     def create_emailed_token_db(self):
  41.         '''create the 6 char token for the form and add it to the db'''
  42.         created_emailed_token = secrets.token_hex(3)
  43.         self.emailed_token = created_emailed_token
  44.         db.session.commit()
  45.    
  46.  
  47.     def count_attempts_token_tried(self):
  48.         self.attempts_token_tried += 1
  49.         db.session.commit()
  50.         # flash(user_db.attempts_token_tried ) # remove after testing.
  51.  
  52.  
  53.     # now is added because of pytest + now represents the current time    
  54.     def create_time_token_db(self, now):
  55.         '''create the time the token lasts/expires and add it to the db'''
  56.         current_time = now
  57.         # add time_token_expired
  58.         thirty_min = timedelta(minutes=30)
  59.         current_time_plus_30_minutes = current_time + thirty_min
  60.         self.time_token_expired = current_time_plus_30_minutes
  61.         db.session.commit()
  62.  
  63.  
  64.  
  65.  
  66.  
  67.     # add description of methods here
  68.  
  69.  
  70.  
  71.     # now is added because of pytest + now represents the current time    
  72.     def check_expired_token(self, now):
  73.         '''      
  74.        The method checks 2 things. It checks if the token has exceeded 30 min and the maximum emails has not been exceeded.
  75.  
  76.        If the time has exceeded 30 min or it has not exceeded 5 emails it makes the token received in the email as 0 and makes the time of the token lasts to 0.
  77.        This happens because I want a new token and a I have 30 min to use the new token.
  78.        '''
  79.  
  80.         time_token_expired_db = self.time_token_expired
  81.         current_time = now
  82.         # current 12:00
  83.         # expired token 12 33
  84.         # ex token created at 9:33pm and token expires at 9:30pm.
  85.         # Wait until the token expires to let the user get more emails.
  86.         #  needed "attempts_token_tried_db <= 5"?
  87.         if current_time > time_token_expired_db and self.attempts_token_tried <= 5:
  88.             # should I just create a new function for pytest?
  89.             self.emailed_token = None
  90.             self.time_token_expired = None
  91.             db.session.commit()
  92.             # only works during pytest
  93.             print('check_expired_token, success')
  94.             flash('Your token has expired. Please click resend email for a new email.')
  95.  
  96.  
  97.  
  98.  
  99.  
  100.     # now is added because of pytest + now represents the current time  
  101.     # is this secure?            
  102.     def wait_max_thirty_min_for_new_token(self, now):
  103.         '''
  104.        Wait a max of 30 min before getting the last emailed token.
  105.        This only happens when creating the last token.
  106.        '''
  107.         time_token_expired_db = self.time_token_expired
  108.         # executes at 9:00 <= 9:30pm
  109.         current_time = now
  110.         if self.attempts_token_tried >= 5 and current_time <= time_token_expired_db:
  111.             # only works duringb pytest
  112.             print('wait_max_thirty_min_for_new_token, success')
  113.             # create times for the created token + expired token
  114.             # better wording.
  115.             flash('You have requested to many tokens. Please wait 30 minutes for a new token from when you recieved youe last token.')
  116.             # is this secure?  
  117.             return 'will redirect to email_login_confirmation route'
  118.        
  119.  
  120.  
  121.  
  122.  
  123.  
  124.     # now is added because of pytest + now represents the current time    
  125.     # is this secure?
  126.     def reset_attempts_token_tried_to_0(route_token_db, now):
  127.         '''
  128.        if the max attempts of the token tried is exceeded + the
  129.        token is expired reset the attwempts_token_tried to 0.
  130.        '''
  131.         # why doesn't work
  132.         time_token_expired_db = route_token_db.time_token_expired
  133.         # executes at 9:00 <= 9:30pm
  134.         current_time = now
  135.  
  136.         if route_token_db.attempts_token_tried >= 5 and current_time >= time_token_expired_db:
  137.             # should I just create a new function for pytest?  
  138.             route_token_db.emailed_token = None
  139.             route_token_db.time_token_expired = None
  140.             route_token_db.attempts_token_tried = 0
  141.             db.session.commit()
  142.  
  143.             # change to print    
  144.             flash('You have waited long enough for a new a token. Please login again and you will be sent a email with instructions before you can login.')
  145.             # redirect to login so I won't redirect /resend_token/<username_db> click on the link and a email is sent automatically.
  146.             # is this secure?
  147.             return 'going to redirect to login'
  148.  
  149.     def __repr__(self):
  150.         return '<User {}>'.format(self.username)
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.     # Creates the token for the route for example .../route_token =  .../485748tyhtg5
  164.     @staticmethod
  165.     def create_route_token(user_db):  
  166.         '''Uses "user_db" for the User's id'''
  167.         SECRET_KEY = 'temp_secret_key'
  168.         serializer = URLSafeTimedSerializer(SECRET_KEY)
  169.         # random number
  170.         data_to_serialize = {'user_id': user_db.id}
  171.         print(f'data_to_serialize={data_to_serialize['user_id']}')
  172.         # 30 minutes
  173.         token = serializer.dumps(data_to_serialize)
  174.         return token    
  175.    
  176.     # check if the token exceeds 30 min and expires
  177.     def check_expired_route_token(self):
  178.         '''
  179.        If the route_token expired make it False else True.
  180.        Uses "user_db" for the User's id
  181.        '''
  182.        
  183.         SECRET_KEY = 'temp_secret_key'
  184.         serializer = URLSafeTimedSerializer(SECRET_KEY)
  185.         try:
  186.             serializer.loads(self.token, max_age=1800)
  187.         except Exception:
  188.             return False
  189.         print('The token works')
  190.         return True
  191.  
  192.     def __repr__(self):
  193.         return '<User {}>'.format(self.email)
  194.  
  195.  
  196.  
  197.  
Advertisement
Add Comment
Please, Sign In to add comment