Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
added invite system
Browse files Browse the repository at this point in the history
  • Loading branch information
pkage committed Jan 18, 2021
1 parent 1127a14 commit ee8565e
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 15 deletions.
39 changes: 39 additions & 0 deletions app/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,43 @@ def service_delete():
flasher(f"Service <code>{svc['display_name']}</code> deleted successfully.", color='success')

return redirect(url_for('dashboard.list_services'))


@bp.route('/invites/new', methods=['POST'])
@admin_login_required
def invite_create():

link = request.form['link'] if 'link' in request.form else None
code = request.form['code'] if 'code' in request.form else None

c = get_db().cursor()
c.execute('''
INSERT INTO Invites (app_id, service, link, code)
VALUES (?,?,?,?)
''', [
request.form['app_id'],
request.form['service'],
link,
code
])

c.connection.commit()

flasher('Created invite successfully!', color='success')

return redirect(url_for('dashboard.list_invites'))


@bp.route('/invites/delete/<inv_id>')
@admin_login_required
def invite_delete(inv_id):
c = get_db().cursor()
c.execute('''
DELETE FROM Invites WHERE id=?
''', [inv_id])

c.connection.commit()

flasher('Deleted invite successfully!', color='success')

return redirect(url_for('dashboard.list_invites'))
22 changes: 22 additions & 0 deletions app/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,28 @@ def edit_config():
strtimes=strtimes
)

@bp.route('/invites')
@admin_login_required
def list_invites():
c = get_db().cursor()

c.execute('''
SELECT i.id, i.app_id, i.service, i.code, i.link, a.email
FROM Invites i
LEFT JOIN Applicants a ON a.user_id=i.app_id
''')

rows = c.fetchall()

if rows is None:
rows = []

return render_template(
'dashboard/invites.html',
session=session,
invites=rows
)

@bp.after_request
def no_cache(response):
response.headers['Cache-Control'] = 'no-store'
Expand Down
14 changes: 9 additions & 5 deletions app/hacker.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,14 +309,18 @@ def status():
def invites():
appl, appl_text = resolve_application(session['email'])

if appl['completed']:
completed_time = arrow.get(appl['completed_time']).format('MMM D, YYYY hh:mm a')
else:
completed_time = ''
c = get_db().cursor()
c.execute('''
SELECT * FROM Invites WHERE app_id=?
''', [appl['user_id']])

rows = c.fetchall()
if rows is None:
rows = []

return render_template(
'hacker/invites.html',
appl=appl_text,
completed_time=completed_time,
invites=rows,
login_type=capitalize_login_provider()
)
4 changes: 4 additions & 0 deletions app/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ CREATE TABLE Votes (
);

CREATE TABLE Invites (
id INTEGER PRIMARY KEY AUTOINCREMENT,
app_id TEXT NOT NULL,
service TEXT NOT NULL,
code TEXT,
link TEXT,

FOREIGN KEY (app_id) REFERENCES Applicants (user_id)
ON DELETE CASCADE ON UPDATE NO ACTION
Expand Down
67 changes: 66 additions & 1 deletion app/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,76 @@ def api_get_all_applicants_csv():
mimetype='text/csv'
)

@bp.route('/invites/create', methods=['POST'])
@service_auth_required
def api_invite_create():
'''
Creates an invite from POSTed JSON.
JSON body:
<pre>
{
"app_id": "applicant_id",
"service": "Service Name",
"code": "(optional) code",
"link": "(optional) link",
}</pre>
'''

link = request.json['link'] if 'link' in request.json else None
code = request.json['code'] if 'code' in request.json else None

if link is None and code is None:
return create_response({}, ok=False, message='Must have either link or code!')

c = get_db().cursor()
c.execute('''
INSERT INTO Invites (app_id, service, link, code)
VALUES (?,?,?,?)
''', [
request.json['app_id'],
request.json['service'],
link,
code
])

c.connection.commit()

return create_response({})

@bp.route('/invites/list')
@service_auth_required
def api_invite_list():
'''
List all the invites in the database.
With an optional parameter `id`, this will return only the invites for the specified `user_id`.
'''

c = get_db().cursor()

if request.args.get('id') is not None:
c.execute('''
SELECT * FROM Invites WHERE app_id=?
''', [request.args.get('id')])
else:
c.execute('''
SELECT * FROM Invites
''')

rows = c.fetchall()
if rows is None:
rows = []

return create_response(rows_to_objs(rows))

api_routes = [
api_config,
api_download_backup,
api_get_by_id,
api_get_by_email,
api_get_all_applicants,
api_get_all_applicants_csv
api_get_all_applicants_csv,
api_invite_create,
api_invite_list
]
17 changes: 10 additions & 7 deletions app/templates/dashboard/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,22 @@
</a>

<div class="navbar-dropdown">
<a class="navbar-item" href="{{url_for('dashboard.export_csv')}}">
Export CSV
</a>
<a class="navbar-item" href="{{url_for('dashboard.admin')}}">
Database Admin
</a>
<a class="navbar-item" href="{{url_for('dashboard.list_services')}}">
Linked Services
</a>
{# <hr class="navbar-divider"> #}
<a class="navbar-item" href="{{url_for('dashboard.list_invites')}}">
Invites
</a>
<a class="navbar-item" href="{{url_for('dashboard.edit_config') }}">
Event Information
</a>
<hr class="navbar-divider">
<a class="navbar-item" href="{{url_for('dashboard.export_csv')}}">
Export CSV
</a>
<a class="navbar-item" href="{{url_for('dashboard.admin')}}">
Database Admin
</a>
</div>
</div>
</div>
Expand Down
90 changes: 90 additions & 0 deletions app/templates/dashboard/invites.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{% extends "dashboard/base.html" %}

{% block dashboard_content %}

<div class="container">
<div class="block">
<table class="table is-striped is-fullwidth">
<thead>
<tr>
<th>Applicant ID</th>
<th>Email</th>
<th>Service</th>
<th>Code</th>
<th>Link</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for invite in invites %}
<tr>
<td>{{invite.app_id}}</td>
<td>{{invite.email}}</td>
<td>{{invite.service }}</td>
<td><code>{{invite.code}}</code></td>
<td><a href="{{invite.link}}">{{ invite.link }}</a></td>
<td>
<a class="has-text-danger" href="{{ url_for('actions.invite_delete', inv_id=invite.id) }}">&times;</a>
</td>

</tr>
{% else %}
<tr>
<td colspan="6">
<i> No invites in DB </i>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>

<div class="block">
<h1 class="title">Create new invite</h1>
<form action="{{ url_for('actions.invite_create') }}" method="POST">
<div class="columns">
<div class="column">
<div class="field">
<label class="label">Applicant ID</label>
<div class="control">
<input class="input" type="text" placeholder="gh:12345" name="app_id" required autocomplete="off">
</div>
</div>
</div>
<div class="column">
<div class="field">
<label class="label">Service</label>
<div class="control">
<input class="input" type="text" placeholder="Discord" name="service" required autocomplete="off">
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column">
<div class="field">
<label class="label">Code</label>
<div class="control">
<input class="input" type="text" placeholder="ABCD" name="code" autocomplete="off">
</div>
</div>
</div>
<div class="column is-two-thirds">
<div class="field">
<label class="label">Link</label>
<div class="control">
<input class="input" type="text" placeholder="https://discord.gg/" name="link" autocomplete="off">
</div>
</div>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button type="submit" class="button is-link">Submit</button>
</div>
</div>
</form>
</div>
<br/>
</div>
{% endblock %}
4 changes: 2 additions & 2 deletions app/templates/dashboard/table.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<tbody>
{% for row in rows %}
<tr>
<td>{{ row['id'] }}</td>
<td>{{ row['user_id'] }}</td>
<td>{{ boolean_val(row['verified']) }}</td>
<td>{{ boolean_val(row['completed']) }}</td>
<td>{{ row['first_name'] }} {{ row['last_name'] }}</td>
Expand All @@ -75,7 +75,7 @@
{% else %}
<tr>
<td colspan="8">
<i> No applicants in DB, upload some from the <a href="{{url_for('dashboard.admin')}}">admin interface. </a></i>
<i> No applicants in DB.</i>
</td>
</tr>
{% endfor %}
Expand Down
25 changes: 25 additions & 0 deletions app/templates/hacker/invites.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
{% extends "hacker/base.html" %}

{% block hacker_content %}

<h1 class="title">Application</h1>

{% if invites | length == 0 %}
<h2 class="subtitle">No invites at this time. Check back later!</h2>
{% else %}
<h2 class="subtitle">
{{ invites|length }} invite{% if invites | length > 1 %}s{%endif%}
</h2>

{% for invite in invites %}
<div class="block box">
<h3 class="is-size-3">{{ invite['service'] }}</h3>
<p>
{% if invite['code'] %}
Invite code: <code>{{ invite['code'] }}</code><br/>
{% endif %}
{% if invite['link'] %}
Link: <a href="{{ invite['link'] }}">{{ invite['link'] }}</a>
{% endif %}
</p>
</div>
{% endfor %}

{% endif %}
{% endblock %}

0 comments on commit ee8565e

Please sign in to comment.