From e58cbef97a382dbafff086e0ecf19710a8da108f Mon Sep 17 00:00:00 2001 From: Daniel Muckerman Date: Sat, 10 Oct 2020 18:21:35 -0400 Subject: [PATCH] Add games page and in progress games list --- Dockerfile | 1 + app.py | 140 ++++++++++++++++++++++++++++++++- config/config.yaml | 29 ++++++- config/games_in_progress.db | Bin 0 -> 16384 bytes requirements.txt | 8 +- static/favicon.png | Bin 0 -> 715 bytes static/images/gameboy.png | Bin 0 -> 156670 bytes static/images/mars.png | Bin 0 -> 407218 bytes static/images/minecraft.png | Bin 0 -> 79311 bytes static/style.css | 37 +++++++++ templates/card_list.j2 | 36 +++++++++ templates/games.j2 | 150 ++++++++++++++++++++++++++++++++++++ templates/index.j2 | 25 ++++-- templates/login.j2 | 37 +++++++++ templates/new_game_modal.j2 | 28 +++++++ 15 files changed, 480 insertions(+), 11 deletions(-) create mode 100644 config/games_in_progress.db create mode 100644 static/favicon.png create mode 100644 static/images/gameboy.png create mode 100644 static/images/mars.png create mode 100644 static/images/minecraft.png create mode 100644 templates/card_list.j2 create mode 100644 templates/games.j2 create mode 100644 templates/login.j2 create mode 100644 templates/new_game_modal.j2 diff --git a/Dockerfile b/Dockerfile index ad6f018..769e8c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,6 +4,7 @@ LABEL maintainer="Dan Muckerman " WORKDIR /project ADD . /project +RUN rm /project/.envrc RUN rm -rf /project/env RUN pip install -r requirements.txt diff --git a/app.py b/app.py index cb8eaa2..d38a0bc 100644 --- a/app.py +++ b/app.py @@ -1,14 +1,33 @@ +import ldap as l +from ldap3 import Server, Connection, ALL, MODIFY_REPLACE from flask import Flask, g, request, session, redirect, url_for, render_template -from flask_bootstrap import Bootstrap +from flask_bs4 import Bootstrap +from flask_simpleldap import LDAP import yaml import datetime as dt import pytz +import os +import sqlite3 app = Flask(__name__) Bootstrap(app) app.secret_key = 'asdf' app.debug = True +# Base +app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication' +app.config['LDAP_HOST'] = os.environ.get('LDAP_HOST') +app.config['LDAP_BASE_DN'] = os.environ.get('LDAP_BASE_DN') +app.config['LDAP_USERNAME'] = os.environ.get('LDAP_USERNAME') +app.config['LDAP_PASSWORD'] = os.environ.get('LDAP_PASSWORD') + +# OpenLDAP +app.config['LDAP_OBJECTS_DN'] = 'dn' +app.config['LDAP_OPENLDAP'] = True +app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=posixAccount)(uid=%s))' + +ldap = LDAP(app) + eastern = pytz.timezone('US/Eastern') with open('config/config.yaml') as f: @@ -18,24 +37,40 @@ search = yaml_data['search'] account_url = yaml_data['accounts']['account_url'] description = yaml_data['description'] +game_description = yaml_data['game_description'] countdown_data = None if yaml_data['countdown']['active'] == True: countdown_data = yaml_data['countdown'] - print(countdown_data) final_countdown_data = None final_time = None if yaml_data['final_countdown']['active'] == True: final_countdown_data = yaml_data['final_countdown'] final_time = eastern.localize(dt.datetime.strptime(final_countdown_data['timestamp'], '%B %d %Y %H:%M:%S%z').replace(tzinfo=None)) - print(final_countdown_data) apps = [] for itm in yaml_data['apps'].items(): apps.append(itm[1]) +games = [] +for itm in yaml_data['games'].items(): + games.append(itm[1]) + + +server = Server(app.config['LDAP_HOST']) +conn = Connection(server, app.config['LDAP_USERNAME'], app.config['LDAP_PASSWORD'], auto_bind=True) + + +@app.before_request +def before_request(): + g.user = None + if 'user_id' in session: + # This is where you'd query your database to get the user info. + g.user = {} + + @app.route('/') def index(): current_time = eastern.localize(dt.datetime.now()) @@ -47,5 +82,104 @@ def index(): return render_template('index.j2', apps = apps, search = search, account_url = account_url, description = description) +@app.route('/games') +def game(): + if 'user_id' in session: + user_dict = ldap.get_object_details(session['user_id']) + user = {'dn': 'cn={},cn=usergroup,ou=users,dc=technicalincompetence,dc=club'.format(user_dict['cn'][0].decode('ascii')), + 'firstName': user_dict['givenName'][0].decode('ascii'), + 'lastName': user_dict['sn'][0].decode('ascii'), + 'email': user_dict['mail'][0].decode('ascii'), + 'userName': user_dict['uid'][0].decode('ascii'), + } + + current_time = eastern.localize(dt.datetime.now()) + if final_countdown_data != None: + if (final_time - current_time).days > -1: + return render_template('final_countdown.j2', final_countdown = final_countdown_data) + if countdown_data != None: + return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description, countdown = countdown_data) + if 'user_id' in session: + return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description, user = user, game_list = generate_game_list()) + return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description) + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if g.user: + return redirect(url_for('index')) + if request.method == 'POST': + user = request.form['user'] + passwd = request.form['passwd'] + test = ldap.bind_user(user, passwd) + if test is None or passwd == '': + return render_template('login.j2', error='Invalid credentials') + else: + session['user_id'] = request.form['user'] + session['passwd'] = request.form['passwd'] + return redirect('/games') + return render_template('login.j2') + + +@ldap.login_required +@app.route('/add', methods=['POST']) +def add_game(): + if request.method == 'POST': + game_title = request.form['game_title'] + game_link = request.form['game_link'] + conn = sqlite3.connect('config/games_in_progress.db') + c = conn.cursor() + + if game_title is not None and len(game_title) > 0 and game_link is not None and len(game_link) > 0: + c.execute("INSERT INTO games (user_id, game_title, game_link) VALUES (?, ?, ?)", (session['user_id'], game_title, game_link,)) + conn.commit() + conn.close() + + return 'Success' + conn.commit() + conn.close() + return 'Error' + + +@ldap.login_required +@app.route('/delete', methods=['POST']) +def delete_game(): + if request.method == 'POST': + game_id = request.form['game_id'] + conn = sqlite3.connect('config/games_in_progress.db') + c = conn.cursor() + + if game_id is not None and len(game_id) > 0: + c.execute("DELETE FROM games WHERE id=? AND user_id=?", (game_id, session['user_id'],)) + conn.commit() + conn.close() + + return 'Success' + conn.commit() + conn.close() + return 'Error' + + +def generate_game_list(): + conn = sqlite3.connect('config/games_in_progress.db') + c = conn.cursor() + + if 'user_id' in session: + c.execute('SELECT * FROM games WHERE user_id=?', (session['user_id'], )) + rows = c.fetchall() + conn.close() + + return rows + + conn.close() + return [] + + +@app.route('/logout') +def logout(): + session.pop('user_id', None) + return redirect(url_for('game')) + + if __name__ == '__main__': app.run(extra_files="config/config.yaml") diff --git a/config/config.yaml b/config/config.yaml index 8e30841..6b0e092 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -6,6 +6,7 @@ accounts: account_url: 'https://account.technicalincompetence.club' description: "It turns out Technical Incompetence's amazingness is just too great for this lame internet - we need a new one to maximize our full potential. Welcome to the Technical Incompetence internet. Population - US." +game_description: "We're all gamers at heart, so welcome to the Valhalla of self hosted gaming. You name it, we have it. Unless we don't. We're gamers, not wizards." countdown: active: False @@ -22,6 +23,11 @@ apps: description: "
The moment you're all been waiting for... Zulip, our chat lord and savior is finally here. Third only to iMessage and AOL - prepare for a superior chatting experience. The move from Slack has never been so sweet. Trust us... you won't be disappointed. There's even a mobile app!" link: "https://zillow.technicalincompetence.club" image: "zulip.png" + rocketchat: + name: "Rocketchat" + description: "
Stay in touch with your friends, family, and people you've never even met with Technical Incompetence's amazing chat service. Experience the joy's of late-1990s AIM all over again." + link: "https://rocketchat.technicalincompetence.club" + image: "rocketchat.png" cloud: name: "Nextcloud" description: "
What would Technical Incompetence be without the ability to give up ownership of all your data and store it on our servers. Don't worry though, our servers will probably never crash or lose data so all you care about is safe with us." @@ -35,7 +41,7 @@ apps: jellyfin: name: "Jellyfin" description: "
Angry about the StReAmInG WaRs? Well our Jellyfin instance has you covered. Listen to all your embarassing weeb music, or watch your barely-not-porn weeb shows and movies. We're not judging you." - link: "http://octotep.com:8096" + link: "https://jellyfin.octotep.com" image: "jellyfin.png" rss: name: "FreshRSS" @@ -47,4 +53,25 @@ apps: description: "
Have you ever felt self conscious about the links you send to people? We feel you. That's why we're proud to introduce our brand new link shortening service! For all those rickrolls you're still sending in current year." link: "https://links.technicalincompetence.club" image: "links.png" + wiki: + name: "Bookstack" + description: "
We did it, we finally got a wiki. All of our history is held here, both recorded and not recorded history, the travels of the drewniverse, and a full explanation of the drewian calendar." + link: "https://wiki.technicalincompetence.club" + image: "wiki.png" +games: + gameboy: + name: "NewGamePlus" + description: "
Too many games, not enough time to play them? Don't worry, we're also slowly sinking into the existential tar pit that is realizing the things you once loved to do fit less and less into your adult life even though they are the very things that hold back the tide of weapons grade ennui that threatens to consume your every waking moment in a boiling pot that will eventually one day bubble over into an anomic explosion of grief, pain, and depression. So that's why we made it easy to keep track of your backlog, checkout NewGamePlus today!" + link: "https://technicalincompetence.games" + image: "gameboy.png" + terraformingmars: + name: "Terraforming Mars" + description: "
Experience the glory of \"cooperative\" gameplay through corporate simulation!" + link: "https://terraforming-mars.flamwenco.com" + image: "mars.png" + minecraft: + name: "Minecraft" + description: "
Remember playing Minecraft in high school? Or that one month on PS4? Or that one Bedrock server we used for a month?

Me neither, but join us in Java Edition at: mc.flamwenco.com" + link: "#" + image: "minecraft.png" \ No newline at end of file diff --git a/config/games_in_progress.db b/config/games_in_progress.db new file mode 100644 index 0000000000000000000000000000000000000000..9e45393f21318e7a7d07f05ab8bc79189a3931f6 GIT binary patch literal 16384 zcmeI(Z%@-e90&003LPWD5tgMsyi6akfP-oLGZTVC8eJR%W*6kqau{p`{0wwF5%PYTuzqdu4H9+@MWMxHQ6 zh`JaXb)#GkQDmv}M(7i`ljHhQ&tOE(E+UmQ>Hu>AIFR zO;da4q+|9}eVk^QU-}o*x*}Vc&J{hkn5#E!>zUPJ%`KZX+l>ZmH|slXYe|I%v4}cJ z8{2xNf|m`FNHRu8deRra3;JGgI3C+>)i-OcJ@&%dTS%VHYHfR~-c%FZw3>Elx>U*- z=BlX?FL1@1%U9(C8K(E0bn2Z-S|n@vsRVmQofe$9H?vvw zzVn8m@*9(rDmNyQ-|riGviomjGP<724fp@g2|ZVJNDzPk1Rwwb2tWV=5P$##AOHaf P{5t|UO*ggle*oFk=F!);U|Nn_7=`Z=6Ua!h z1852GIsoSL1@%>6{-0x~Nw&ak$qKL;xI$v^h5*R-FrWYX{E2J}b_GO$X;4UD3kAA` z0LUTOq65PL$ng&I`M=9IY34ATApo)*-C`CiQ@9+=VNAN}a5ge{{Tz~WMI{lTzSKM% zO#3Za1(pnq31A#Ni4Yd_^NMo7e2|Zxm*;`mlAV*lG`4Jr?sG?RZ7{u`;VPI0g#>aa z;B>%10SpHq`-r7rBA9+YAsP@%07~2u;d68#C&CY= zL1tjf5dM2h%(1v@z7k zKxvO@kPEZGz6Y+#i=$w6QV}uIW&|$Ak6rA>@Il@pa;Nk z0CJ)6Zx19s6_lPqB$cFa8l-S^Hkkf*59)Ojh}xfv5WdHj9S1%H(j^VSjFjEG!89y4 zfL-~V4a}Bt!R>Q6fQHVJ+M^J@i3{AEJNF)f*_PG{VA}8GDliRhkj#939;cZwjd#)^ z^rJ8D!1OdW%tV#-OBsbff74+weH>~A2!IMDbTIHypcZI{Qbnb#-;GgV!@5}uj~@fm zGfx}@(`;R>49YII2ggHr&Q(DJbaS4j|j(Sqztk{m#9002H6_TTi|Yh(Zb002ovPDHLkV1l=nGI#(0 literal 0 HcmV?d00001 diff --git a/static/images/gameboy.png b/static/images/gameboy.png new file mode 100644 index 0000000000000000000000000000000000000000..891c006eef90e7e459f8bb36d813fa304409cf74 GIT binary patch literal 156670 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