· 4 years ago · Mar 24, 2021, 05:52 PM
1from colorama import Fore # for debugging in the terminal
2
3# region for encryption
4from cryptography.fernet import Fernet
5from cryptography.hazmat.backends import default_backend
6from cryptography.hazmat.primitives import hashes
7from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
8# endregion
9
10# region db (mysql)
11# import mysql.connect # on hold for the time being
12
13from sqlalchemy.ext.automap import automap_base
14from sqlalchemy.ext.declarative import declarative_base
15from sqlalchemy.orm import Session, sessionmaker # i don't know why this is used
16from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData
17
18# import pandas as pd # for getting the information from the database
19# import pymysql # the database? i guess
20from dotenv import load_dotenv # using .env files for more security
21from pathlib import Path # python3 only
22# connecting to the linode database
23from flask_sqlalchemy import SQLAlchemy
24
25# endregion
26
27# region flask
28from flask import * # the usage of the api
29# endregion
30
31# region other libraries
32from os import system, name # clear the screen
33import base64 # for encryption
34import string # generating api and other random strings
35import random # generating api and other random strings
36import json # using the data from mobile app
37import os # os specific data
38import datetime # for getting the date time
39from datetime import timedelta # TODO: "Delete later."
40import colorama # for debugging in the terminal
41import cryptography # not sure why it's showing that it's not being used
42# endregion
43
44# region debugging in terminals
45colorama.init(autoreset=True) # to make the console colors work
46
47# colors for the console
48error = Fore.RED # error
49warning = Fore.YELLOW # if there's a possible error
50success = Fore.GREEN # will show when there's 0 errors
51# endregion
52
53# initiate the flask web framework
54app = Flask(__name__)
55
56load_dotenv() # loading needed .env files.
57
58# information for copywritten
59__creator__ = "Pombo Technologies"
60__version__ = 0.007
61
62
63# region loading up the .env files
64
65
66class Config(object): # for env
67 DEBUG = False
68 TESTING = False
69 CSRF_ENABLED = True
70 SQLALCHEMY_TRACK_MODIFICATIONS = True
71 # SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")
72
73 SESSION_COOKIE_SECURE = True
74 SESSION_COOKIE_HTTPONLY = True
75 SESSION_COOKIE_SAMESITE = 'None'
76
77 # mailing
78 MAIL_SERVER = 'smtp.gmail.com'
79 MAIL_PORT = 465
80 MAIL_USE_TLS = False
81 MAIL_USE_SSL = True
82 MAIL_USERNAME = os.environ.get("MAIL_USERNAME")
83 MAIL_PASSWORD = os.environ.get("MAIL_PASSWORD")
84
85 # db
86 username = os.getenv("USERNAME")
87 password = os.getenv("PASSWORD")
88 ip = os.getenv("IP")
89 db = os.getenv("DB")
90
91 hosting = os.getenv("hosting")
92 Debugging = os.getenv("debugging")
93
94
95class ProductionConfig(Config):
96 DEBUG = False
97 SECRET_KEY = "9asdf8980as8df9809sf6a6ds4f3435fa64ˆGggd76HSD57hsˆSDnb"
98 SQLALCHEMY_TRACK_MODIFICATIONS = False
99
100
101class DevelopmentConfig(Config):
102 ENV = "development"
103 DEVELOPMENT = True
104 SECRET_KEY = "secret_for_test_environment"
105 OAUTHLIB_INSECURE_TRANSPORT = True
106 SQLALCHEMY_TRACK_MODIFICATIONS = True
107
108# endregion
109
110
111# region global variables
112FORMAT = "utf-8" # into bytes
113
114app.config["SQLALCHEMY_DATABASE_URI"] = f'mysql+pymysql://{Config.username}:{Config.password}@{Config.ip}/{Config.db}'
115app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
116db = SQLAlchemy(app)
117
118# endregion
119
120
121# region connect TODO: Delete later
122# try:
123# # 10.87.107.19 (66.228.52.158)
124# host_ip = "66.228.52.158"
125# db_user = "username"
126# db_psw = "Asdf@1234"
127# db_name = "Flow"
128# Port = 3306
129
130# """
131# user='myuser',
132# password='mypassword',
133# host='localhost',
134# port='3306',
135# database='mydb'
136# """
137# mydb = mysql.reador.read(
138# user=db_user,
139# password=db_psw,
140# host=host_ip,
141# port=Port,
142# database=db_name
143# # ,
144# # auth_plugin="mysql_native_password"
145# )
146
147# except Exception as e:
148# print(f"{Fore.GREEN} * error: {str(e)}")
149
150# region. other functions for mysql
151# def get_user_login(username):
152# try:
153# mycursor = mydb.cursor()
154
155# sql = f"SELECT * FROM `users` WHERE `user-name` = '{username}'"
156# mycursor.execute(sql)
157
158# # true = user exist
159# # false = user does not exist
160# if mydb.commit():
161# if mycursor.fetchone():
162# return True
163# else:
164# return False
165
166# else:
167# print("error with getting the information from the database")
168
169# except Exception as e:
170# print(f"{error} error {str(e)}")
171
172
173# def insertNewUser(useremail, password, date, apiKey):
174# # inserting new users via email and password
175# try:
176# mycursor = mydb.cursor()
177
178# sql = "INSERT INTO `users`(`user-name`, `email`, `password`, `user-preference`, `date-created`, `api-key`) VALUES (%s, %s, %s, %s, %s, %s)"
179# val = (useremail, useremail, password, "", date, "")
180# mycursor.execute(sql, val)
181
182# if get_user_login(useremail) == False:
183# if mydb.commit():
184# return True
185# else:
186# return False
187
188# except Exception as e:
189# print(f"{error} * error: {str(e)}")
190
191
192# def all(): # debugging purposes
193# try:
194# mycursor = mydb.cursor()
195
196# sql = "SELECT * FROM `users`"
197# mycursor.execute(sql)
198
199# myresult = mycursor.fetchall()
200
201# if mydb.commit():
202# for x in myresult:
203# print(x)
204
205# return True
206# else:
207# return False
208
209# except Exception as e:
210# print(f"{error} * error: {str(e)}")
211# endregion
212# endregion
213
214try:
215 # region tba delete later if works
216 # maingEngine = create_engine(
217 # f'mysql+pymysql://{Config.username}:{Config.password}@{Config.ip}/{Config.db}'
218 # )
219
220 # # testing it?
221 # db = pd.read_sql('SELECT * FROM users', maingEngine)
222
223 # # to be used with creating engine for mysql connection
224 # meta = MetaData()
225
226 # connect = maingEngine.connect()
227
228 # # table
229 # Users = Table(
230 # 'Users', meta,
231 # Column('id', Integer, primary_key=True),
232
233 # # region null if (apple fb or google username?)
234 # Column('username', String(255)),
235 # Column('password', String(255)),
236 # # endregion
237
238 # Column('email', String(255)), # email
239 # Column('user_Preference', String(255)), # (for later use not now)
240 # Column('date_created', String(255)), # date created
241 # Column('Api_Key', String(255)), # api key to access from mobile
242 # # for saving (apple, facebook, google)
243 # Column('login_type', String(255)),
244 # )
245
246 # base = declarative_base()
247
248 # class User(base):
249 # __tablename__ = 'usEr'
250 # id = Column(Integer, primary_key=True)
251 # name = Column(String(50))
252
253 # meta.create_all(maingEngine) # create table
254 # # meta.reflect()
255 # # table = meta.tables["events"]
256
257 # Session = sessionmaker(bind=maingEngine)
258 # session = Session()
259 # endregion
260
261 class Users(db.Model):
262 __tablename__ = "Users"
263 _id = db.Column("Id", db.Integer, primary_key=True)
264 username = db.Column(db.String(255))
265 password = db.Column(db.String(255))
266 email = db.Column(db.String(255))
267 user_Preference = db.Column(db.String(255))
268 date_created = db.Column(db.String(255))
269 api_key = db.Column(db.String(255))
270 login_type = db.Column(db.String(255))
271
272 def __init__(self, username, password, email, user_Preference, date_created, api_key, login_type):
273 self.username = username
274 self.password = password
275 self.email = email
276 self.user_Preference = user_Preference
277 self.date_created = date_created
278 self.api_key = api_key
279 self.login_type = login_type
280
281
282except Exception as e:
283 print(f"{error} {str(e)}")
284
285
286def insertUSR(username, user_email, userpassword, date, apikey, preference, login_type):
287 # inserting new user into the database
288 try:
289 if login_type == 'apple' or login_type == 'facebook' or login_type == 'google':
290 pass
291 else:
292 # passing in the new user into the database
293 newUSR = Users(
294 username=username,
295 password=userpassword,
296 email=user_email,
297 user_Preference=preference,
298 date_created=date,
299 api_key=apikey,
300 login_type=login_type
301 )
302
303 db.session.add(newUSR)
304 result = db.session.commit()
305
306 # if the new user has been inserted
307 if result:
308 return True
309 else:
310 return False
311
312 except Exception as e:
313 log(str(e))
314 print(f"{error} error: {str(e)}")
315
316
317def getUser(useremail): # getting the user via email and password
318 try:
319 # reading session.query_property()
320 useremail = Users.query.filter_by(email=useremail).first()
321
322 if useremail:
323 return True
324 else:
325 return False
326
327 except Exception as e:
328 print(f" error in get user {str(e)}")
329
330
331# region testing
332def insertTest(username, useremail, password, date_created, preference, apikey, login_type):
333 try:
334 # passing in the new user into the database
335 newUSR = Users(
336 username=username,
337 password=password,
338 email=useremail,
339 user_Preference=preference,
340 date_created=date_created,
341 api_key=apikey,
342 login_type=login_type
343 )
344
345 db.session.add(newUSR)
346 result = db.session.commit()
347
348 # if the new user has been inserted
349 if result:
350 return short_json_dump("User " + username, "inserted properly")
351 else:
352 return short_json_dump("User " + username, "error inserted properly")
353
354 except Exception as e:
355 print(f"{error} * error: {str(e)} ")
356
357
358@app.route('/', methods=["GET"])
359def func_name():
360 return "<h1>It works, and it will continue working. </h1>"
361
362
363@app.route('/api/createuser', methods=['POST'])
364def createUSR(): # creating an user via post method
365 try:
366 data = json.loads(request.data) # load incoming data
367
368 if request.method == "POST":
369 # testing
370 print(f"{Fore.GREEN} {data}")
371
372 # making sense of incoming json data
373 useremail = data['email']
374 user_psw = data['password']
375 logonType = data['login_type'] # json
376
377 # region data
378 useremail = str(useremail).strip()
379 user_psw = str(user_psw).strip()
380
381 # encryption
382 user_password = encrypt(user_psw)
383
384 date = get_Date() # setting the date of the creation of account
385
386 # generate the api key to be able to access via phone
387 key = genAPIKey(20)
388
389 # def insertUSR(username, user_email, userpassword, date, apikey, preference, login_type):
390
391 # if the user continues with email and password route
392 ins_usr = insertUSR(
393 "", useremail, user_password, date, key, None, logonType)
394
395 # error checking for email and password
396 if ins_usr == True:
397 return short_json_dump("Server", "Data inserted with email password route")
398 else:
399 return short_json_dump("Server", "error inserting the data")
400
401 else:
402 return short_json_dump("Error", "Unkown error happened either on the server or mobile device")
403
404 # endregion
405
406 except Exception as e:
407 log(str(e)) # logging any known errors.
408 print(f"{error} error: {str(e)}")
409
410
411@app.route('/api/getEmailUser')
412def getUSR(): # creating an user via post method
413 try:
414 data = json.loads(request.data) # load incoming data
415
416 # testing
417 print(f"{Fore.GREEN} {data}")
418
419 # making sense of incoming json data
420 useremail = data['email']
421 user_psw = data['password']
422
423 # region data
424 useremail = str(useremail).strip()
425 user_psw = str(user_psw).strip()
426
427 # encryption
428 # user_password = encrypt(user_psw)
429
430 # def insertUSR(username, user_email, userpassword, date, apikey, preference, login_type):
431
432 # if the user continues with email and password route
433 getusr = getUser(useremail)
434
435 # error checking for email and password
436 if getusr == True:
437 return short_json_dump("Server", "Login the user")
438 else:
439 return short_json_dump("Server", "error inserting the data")
440
441 except Exception as e:
442 log(str(e)) # logging any known errors.
443 print(f"{error} error: {str(e)}")
444
445
446@app.route('/autor')
447def author(): # cheeky little function
448 return f"Software developed and owned by {str(__creator__)}"
449
450# region usefull functions
451
452
453def tipe(obj): # printing out the type of methods
454 print(type(obj))
455
456
457def short_json_dump(title, data): # short json
458 return json.dumps(
459 {
460 title: data
461 }
462 )
463
464
465def RecoverAccountEmail(email): # using emails
466 pass
467
468
469def get_encryption_key(msg): # generate encryption key to encrypt lol
470 try:
471 # stripping any white spaces
472 password_provided = str(msg).strip()
473
474 # encoding into a byte
475 password = str(password_provided).encode(FORMAT)
476
477 # salt used to encrypt
478 # salt = b"\xb9\x1f|}'S\xa1\x96\xeb\x154\x04\x88\xf3\xdf\x05"
479 salt = os.urandom(32)
480
481 # generating said key
482 kdf = PBKDF2HMAC(
483 algorithm=hashes.SHA256(),
484 length=32,
485 salt=salt,
486 iterations=100000,
487 backend=default_backend()
488 )
489
490 # encrypt it?
491 key = base64.urlsafe_b64encode(kdf.derive(password))
492
493 return key # this is the key that'll be used for encryption
494
495 except Exception as e:
496 print(f"{error} * Error: {str(e)}")
497
498
499def encrypt(data): # encrypt
500 try:
501 # encrypt data
502 fernet = Fernet(
503 get_encryption_key(
504 data.encode(FORMAT)
505 )
506 )
507 return fernet.encrypt(
508 data.encode(FORMAT)
509 )
510 except Exception as e:
511 print(f"{error} * error: {str(e)}")
512
513
514def decrypt(data): # decrypt
515 try:
516 # decrypt data
517 fernet = Fernet(
518 get_encryption_key(
519 data
520 )
521 )
522 return fernet.decrypt(
523 data
524 )
525 except Exception as e:
526 print(f"{error} * error: {str(e)}")
527
528
529def get_time(): # get full 12 hour time
530 x = datetime.datetime.now()
531
532 hour = x.strftime("%I") # hour
533 min = x.strftime("%M") # minute
534 AMPM = x.strftime("%p") # am / pm
535
536 return f"{hour} : {min} : {AMPM}"
537
538
539def get_Date(): # get full date
540 return datetime.datetime.now().strftime("%x")
541
542
543def log(msg): # writing a .txt file with the errors in a list
544 # make this into an excel file or something more readable and user friendly
545 """
546 log number being written.
547 get the date and time
548 and showing the log
549 """
550 f = open("./err_log/log.txt", "a")
551 f.write(
552 f"\n\n________________________________\n" +
553 f" log id: {rnd(1000000)} \n" +
554 f"________________________________\n" +
555 f" date: {get_Date()} \n" +
556 f"________________________________\n" +
557 f" time: {get_time()} \n" +
558 f"________________________________\n" +
559 f" error log: {msg} \n" +
560 f"________________________________\n"
561 )
562 f.close()
563
564 print(f"{error}Error logged into log.txt........")
565
566
567def genAPIKey(N): # generating the random api key and saving it with each user
568 return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(N))
569
570
571def rnd(last): # random number generator for choosing 1
572 return random.randint(1, last)
573
574
575def cls():
576 # for windows
577 if name == 'nt':
578 _ = system('cls')
579
580 # for mac and linux(here, os.name is 'posix')
581 else:
582 _ = system('clear')
583
584# endregion
585# ignore this line, again
586
587
588def run(): # DO NOT DELETE THIS!!!!!
589 try:
590 # , host=Config.hosting, debug=Config.Debugging
591 db.create_all()
592 app.run(threaded=True, port=5000)
593 except Exception as e:
594 log(str(e)) # logging any known errors.
595 print(f"{error} * error: {str(e)}")
596
597
598if __name__ == '__main__': # the start of the api
599 run()
600