Skip to content
Snippets Groups Projects
main.py 7.62 KiB
Newer Older
Jonas Leder's avatar
Jonas Leder committed
#!/usr/bin/env python3
from waitress import serve #Used as webserver (Production)
Jonas Leder's avatar
Jonas Leder committed
from flask import Flask, request, render_template, redirect, abort, Markup, session, make_response, jsonify #Used to prepare the dynamic pages
Jonas Leder's avatar
Jonas Leder committed
import sqlite3 #Used to store the Data
import os #Used for getting the enviorement variables
from itsdangerous import URLSafeSerializer #used for signing the cookies
import random #used for signing the cookies
import string #used for signing the cookies
from table_check import table_check #import the table check file
from makeqr import makeQR #Qr code generation tool
from grecaptcha_verify import grecaptcha_verify #Tool to verify the google recaptcha response
from newurl import newurl #Script to add the new urls to the database
from redirectShortenURL import redirectShortenURL #Script to redirect the user to the long site
from login import login #thandles the login
from home import home #returns the main page
from googlecallback import googleCallback #Script to handle the google oauth login
from githubcallback import githubCallback #Script to handle the Github oauth login
from userprofile import userProfile #This script handles the overview of the own links
from deletelink import deleteLink #Script to delete Links of Users, if they want.
from api import apiGet,apiPost #Scripts to handle the API
Jonas Leder's avatar
Jonas Leder committed
app = Flask(__name__)
Jonas Leder's avatar
Jonas Leder committed
domain_to_index = {}

try:
    domain = os.environ["domains"].split(";") #Get the domains from the enviorement variable. If no enviorement variable is set set it to 127.0.0.1:5000 (for testing)
except:
    domain = ["localhost:5000", "127.0.0.1:5000"]
Jonas Leder's avatar
Jonas Leder committed

try:
    if(os.environ["show_build_date"] == "1"): #If you want to see the builddate you can enable this enviorement variable
        builddate = open("builddate.txt", "r").read()
Jonas Leder's avatar
Jonas Leder committed
    else:
        builddate = ""
Jonas Leder's avatar
Jonas Leder committed
except:
Jonas Leder's avatar
Jonas Leder committed
    builddate = "" #If the enviorement Variable is not set also skip the builddate
Jonas Leder's avatar
Jonas Leder committed

try:
    if(os.environ["show_version"] == "1"): #If you want to see the builddate you can enable this enviorement variable
        version = open("VERSION", "r").read()
Jonas Leder's avatar
Jonas Leder committed
    else:
        version = ""
Jonas Leder's avatar
Jonas Leder committed
    version = "" #If the enviorement Variable is not set also skip the version
Jonas Leder's avatar
Jonas Leder committed
try:
Jonas Leder's avatar
Jonas Leder committed
    recaptchaPrivateKey = os.environ["recaptcha_private"] #Get the recaptcha keys, if not set set skipRecaptcha to true to skip the check. If the publicKey is not set the user also will not get the code needed for recaptcha delivered in the page.
Jonas Leder's avatar
Jonas Leder committed
    recaptchaPublicKey = os.environ["recaptcha_public"]
Jonas Leder's avatar
Jonas Leder committed
    if(recaptchaPrivateKey != "") and (recaptchaPublicKey != ""): #If the variables are empty also skip the captcha
        skipCaptcha = False
    else:
        skipCaptcha = True

Jonas Leder's avatar
Jonas Leder committed
except:
    recaptchaPrivateKey = ""
    recaptchaPublicKey = ""
Jonas Leder's avatar
Jonas Leder committed
    skipCaptcha = True

Jonas Leder's avatar
Jonas Leder committed
try:
    if(os.environ["production"] == "1"): #If you use this in production, please set this to 1, because the Flask Testserver is not very secure (e.g. shows error on Website)
        production = True
    else:
        production = False
except:
    production = False

Jonas Leder's avatar
Jonas Leder committed
try: #If you use https with a proxy afterwards you can set this to https and internal redirects will be https not http. This is to prevent bugs with modern browsers, bacause they block http content if the main page is loaded via https.
Jonas Leder's avatar
Jonas Leder committed
    url_scheme = os.environ["url_scheme"]
except:
    url_scheme = "http"

try:
    host=os.environ["host"]
except:
    host="127.0.0.1"

    GITHUB_CLIENT_ID = os.environ['GITHUB_CLIENT_ID']
    GITHUB_CLIENT_SECRET = os.environ['GITHUB_CLIENT_SECRET']
    GOOGLE_CLIENT_ID = os.environ['GOOGLE_CLIENT_ID']
    GOOGLE_CLIENT_SECRET = os.environ['GOOGLE_CLIENT_SECRET']
    print("please set the oauth keys and run again.")
Jonas Leder's avatar
Jonas Leder committed
try:
    if(os.environ["cookieNotice"] == 1):
        cookieNotice = True
    else:
        cookieNotice = False
except:
    cookieNotice = True

try:
    secretKey = open("db/secretKey.txt", "r").read()
except:
    secretKey = ''.join(random.choice(string.ascii_lowercase) for i in range(100)) #If we can't find the secret key(first run) we generate it in this step and write it to a file
    print("generated secret Key. Key is: " + secretKey)
    f = open("db/secretKey.txt", "w")
    f.write(secretKey)
    f.close()
    secretKey = open("db/secretKey.txt", "r").read()
s = URLSafeSerializer(secretKey)
Jonas Leder's avatar
Jonas Leder committed
sAPI = URLSafeSerializer("api_key_" + secretKey)
Jonas Leder's avatar
Jonas Leder committed
index = 0
Jonas Leder's avatar
Jonas Leder committed
domain_prepared = ""
Jonas Leder's avatar
Jonas Leder committed
for domains in domain: #Make from every domnain a entry for the select box later
    domain_prepared = domain_prepared + '<option value="' + str(domains) + '">' + str(domains) + '</option>'
    domain_to_index[domains] = str(index)
    index = index + 1
if(index > 1):
    showDomainSelect=True #Show only domain select, if there are more than one available
else:
Jonas Leder's avatar
Jonas Leder committed
    showDomainSelect=False
    domain_prepared = domain[0]
Jonas Leder's avatar
Jonas Leder committed


@app.route('/', methods=['GET'])
def home_get():
    return home(request, builddate, version, domain_prepared, recaptchaPublicKey, showDomainSelect, cookieNotice, domain_to_index, s)
Jonas Leder's avatar
Jonas Leder committed

@app.route('/', methods=['POST']) #This function is used to create a new url
def home_post():
    return newurl(request, skipCaptcha, recaptchaPrivateKey, recaptchaPublicKey, builddate, version, domain_prepared, domain_to_index, showDomainSelect, cookieNotice, s, url_scheme)

Jonas Leder's avatar
Jonas Leder committed
@app.route('/favicon.ico') #Redirect to the static url of the favicon
def favicon():
    return redirect("/static/favicon.ico")

@app.route('/<short_url>')
def redirect_short_url(short_url):
    return redirectShortenURL(request, short_url)
@app.route('/user/login')
def loginPage():
    return login(request, GITHUB_CLIENT_ID, cookieNotice, GOOGLE_CLIENT_ID, url_scheme, domain)

@app.route("/user/google-callback")
def authorizeGoogle():
    return googleCallback(request, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, url_scheme, domain, s)
@app.route('/user/github-callback') #Github redirects to this link after the user authenticated. Then we use the Token we get from github and request via the github api the username and the userid
def authorizeGithub():
    return githubCallback(request, GITHUB_CLIENT_SECRET, GITHUB_CLIENT_ID, s)
@app.route('/user/logout')
Jonas Leder's avatar
Jonas Leder committed
    resp = make_response("logout successful")
    resp.set_cookie('userID', "", max_age=0) #Set the max age of the cookies to 0, this means delete the cookies.
    resp.set_cookie('username', "", max_age=0)
    return resp
@app.route('/user/links')#This function gives the user the posibility to see and delete his links
    return userProfile(request, cookieNotice, s)
@app.route('/user/delete') #This function is called if a user deletes an entrie
Jonas Leder's avatar
Jonas Leder committed
def delete():
    return deleteLink(request, s)
Jonas Leder's avatar
Jonas Leder committed
@app.route('/user/makeqr')
def makeQrCode():
    link = request.args.get('link')
    return "data:image/jpeg;base64," + makeQR(url_scheme + "://" + link)
Jonas Leder's avatar
Jonas Leder committed

Jonas Leder's avatar
Jonas Leder committed
@app.route('/user/api', methods=['POST'])
def api():
    return apiPost(request, domain)

Jonas Leder's avatar
Jonas Leder committed

@app.route('/user/api', methods=['GET'])
def apiDocs():
    return apiGet(request, url_scheme)
Jonas Leder's avatar
Jonas Leder committed

Jonas Leder's avatar
Jonas Leder committed
if __name__ == '__main__':
    table_check()# This code checks whether database table is created or not
    if production: #Check if production variable is set to true use the waitress webserver, else use the buildin flask webserver, with more debug output
        serve(app, host=host, port= 5000, url_scheme=url_scheme) #Start the Webserver for all users on port 5000
Jonas Leder's avatar
Jonas Leder committed
    else:
        app.run(host=host, port=5000, debug=True) #Start the Webserver in Debug mode. This means, if the script runs in an error, it will show the error message in Browser.