diff --git a/ocfweb/account/commands.py b/ocfweb/account/commands.py index 8d5545640..e87fb19dc 100644 --- a/ocfweb/account/commands.py +++ b/ocfweb/account/commands.py @@ -25,14 +25,21 @@ def commands(request: HttpRequest) -> HttpResponse: ssh = SSHClient() host_keys = ssh.get_host_keys() - entry = HostKeyEntry.from_line( + entry_ed25519 = HostKeyEntry.from_line( + 'ssh.ocf.berkeley.edu ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPm+RlDujsxQyxFTEOCTeImSBDvr63cL8Kg+rNrH6NK8', # noqa + ) + entry_rsa = HostKeyEntry.from_line( 'ssh.ocf.berkeley.edu ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqMkHVVoMl8md25iky7e2Xe3ARaC4H1PbIpv5Y+xT4KOT17gGvFSmfjGyW9P8ZTyqxq560iWdyELIn7efaGPbkUo9retcnT6WLmuh9nRIYwb6w7BGEEvlblBmH27Fkgt7JQ6+1sr5teuABfIMg22WTQAeDQe1jg0XsPu36OjbC7HjA3BXsiNBpxKDolYIXWzOD+r9FxZLP0lawh8dl//O5FW4ha1IbHklq2i9Mgl79wAH3jxf66kQJTvLmalKnQ0Dbp2+vYGGhIjVFXlGSzKsHAVhuVD6TBXZbxWOYoXanS7CC43MrEtBYYnc6zMn/k/rH0V+WeRhuzTnr/OZGJbBBw==', # noqa ) - assert entry is not None # should never be none as we are passing a static string above + host_keys.add( + 'ssh.ocf.berkeley.edu', + 'ssh-ed25519', + entry_ed25519.key, + ) host_keys.add( 'ssh.ocf.berkeley.edu', 'ssh-rsa', - entry.key, + entry_rsa.key, ) try: @@ -45,6 +52,8 @@ def commands(request: HttpRequest) -> HttpResponse: error = 'Authentication failed. Did you type the wrong username or password?' if not error: + if command_to_run == 'paper': + command_to_run = f"/run/current-system/sw/bin/paper view {username} | sed 's/\x1B\\[[0-9;]*[a-zA-Z]//g'" # noqa _, ssh_stdout, ssh_stderr = ssh.exec_command(command_to_run, get_pty=True) output = ssh_stdout.read().decode() error = ssh_stderr.read().decode() @@ -78,7 +87,7 @@ class CommandForm(Form): COMMAND_CHOICES = ( ( - '/opt/share/utils/bin/paper', + 'paper', 'paper quota -- how many pages you have remaining this semester', ), ( diff --git a/ocfweb/account/info.py b/ocfweb/account/info.py new file mode 100644 index 000000000..fcd9307f5 --- /dev/null +++ b/ocfweb/account/info.py @@ -0,0 +1,101 @@ +from django import forms +from django.http import HttpRequest +from django.http import HttpResponse +from django.shortcuts import render +from ocflib.printing.quota import get_connection +from ocflib.printing.quota import get_quota +from ocflib.vhost.application import get_app_vhosts +from ocflib.vhost.mail import vhosts_for_user +from ocflib.vhost.web import get_vhosts +from paramiko import AuthenticationException +from paramiko import SSHClient +from paramiko.hostkeys import HostKeyEntry + +from ocfweb.auth import login_required +from ocfweb.component.forms import Form +from ocfweb.component.session import logged_in_user + + +@login_required +def account_info(request: HttpRequest) -> HttpResponse: + user = logged_in_user(request) + # user = 'animage' # test + with get_connection() as c: + paper_quota = get_quota(c, user) + bytes_used = None + bytes_total = None + error = '' + if request.method == 'POST': + form = PasswordForm(request.POST) + if form.is_valid(): + password = form.cleaned_data['password'] + ssh = SSHClient() + host_keys = ssh.get_host_keys() + entry_ed25519 = HostKeyEntry.from_line( + 'ssh.ocf.berkeley.edu ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPm+RlDujsxQyxFTEOCTeImSBDvr63cL8Kg+rNrH6NK8', # noqa + ) + entry_rsa = HostKeyEntry.from_line( + 'ssh.ocf.berkeley.edu ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqMkHVVoMl8md25iky7e2Xe3ARaC4H1PbIpv5Y+xT4KOT17gGvFSmfjGyW9P8ZTyqxq560iWdyELIn7efaGPbkUo9retcnT6WLmuh9nRIYwb6w7BGEEvlblBmH27Fkgt7JQ6+1sr5teuABfIMg22WTQAeDQe1jg0XsPu36OjbC7HjA3BXsiNBpxKDolYIXWzOD+r9FxZLP0lawh8dl//O5FW4ha1IbHklq2i9Mgl79wAH3jxf66kQJTvLmalKnQ0Dbp2+vYGGhIjVFXlGSzKsHAVhuVD6TBXZbxWOYoXanS7CC43MrEtBYYnc6zMn/k/rH0V+WeRhuzTnr/OZGJbBBw==', # noqa + ) + host_keys.add( + 'ssh.ocf.berkeley.edu', + 'ssh-ed25519', + entry_ed25519.key, + ) + host_keys.add( + 'ssh.ocf.berkeley.edu', + 'ssh-rsa', + entry_rsa.key, + ) + + try: + ssh.connect( + 'ssh.ocf.berkeley.edu', + username=user, + password=password, + ) + except AuthenticationException: + error = 'Authentication failed. Did you type the wrong password?' + + if not error: + quota_command = "/run/current-system/sw/bin/quota 2>/dev/null | awk 'NR==4 {print $1, $2}'" + _, ssh_stdout, _ = ssh.exec_command(quota_command, get_pty=True) + sizes = ssh_stdout.read().decode().split() + if len(sizes) == 2: + bytes_used, bytes_total = (int(size) * 1024 for size in sizes) + else: + error = 'Unable to get quota information from the server. Please try again later.' + else: + form = PasswordForm() + + return render( + request, + 'account/info/index.html', { + 'title': 'My Account', + 'form': form, + 'error': error, + 'paper_quota': paper_quota, + 'bytes_used': bytes_used, + 'bytes_total': bytes_total, + 'vhosts': [ + {'host': host, 'aliases': val['aliases']} + for host, val in get_vhosts().items() + if val['username'] == user + ], + 'vhosts_app': [ + {'host': host, 'aliases': val['aliases']} + for host, val in get_app_vhosts().items() + if val['username'] == user + ], + 'vhosts_mail': vhosts_for_user(user), + }, + ) + + +class PasswordForm(Form): + password = forms.CharField( + widget=forms.PasswordInput, + label='', + min_length=8, + max_length=256, + ) diff --git a/ocfweb/account/templates/account/info/index.html b/ocfweb/account/templates/account/info/index.html new file mode 100644 index 000000000..7f5ba7d57 --- /dev/null +++ b/ocfweb/account/templates/account/info/index.html @@ -0,0 +1,75 @@ +{% extends "base.html" %} +{% load bootstrap %} + +{% block content %} +
You are logged in as {{user}}, which is {{ user_is_group|yesno:"a group,an individual" }} account.
+ {% if user_is_group %} +Group accounts can't print. Sorry!
+ {% else %} +You currently have:
+Please re-enter your OCF password to check your personal storage.
+ + {% if error %} +{{ error }}
+ {% endif %} + {% else %} +You have used {{ bytes_used|filesizeformat }} out of {{ bytes_total|filesizeformat }} available in disk storage on the OCF servers.
+ {% endif %} + {% if user_is_group or vhosts or vhosts_app or vhosts_mail %} + {% if vhosts %} +Your account has web virtual hosting at:
+{{vhost.host}}{% if vhost.aliases %} with alias{{ vhost.aliases|pluralize:"es" }} {% for vhost_alias in vhost.aliases %} {{vhost_alias}}{% endfor %}{% endif %}Your account is not yet set up for web virtual hosting.
+ {% endif %} + {% if vhosts_app %} +Your account has web application hosting at:
+{{vhost_app.host}}{% if vhost_app.aliases %} with alias{{ vhost_app.aliases|pluralize:"es" }} {% for vhost_app_alias in vhost_app.aliases %} {{vhost_app_alias}}{% endfor %}{% endif %}Your account is not yet set up for web application hosting.
+ {% endif %} + {% if vhosts_mail %} +Your account has mail virtual hosting at:
+{{vhost_mail.domain}}Your account is not yet set up for mail virtual hosting.
+ {% endif %} + {% else %} +Only group, faculty, and staff accounts are eligible for virtual hosting. Sorry!
+ {% endif %} +You can also check this information via SSH by running paper view {{user}}, quota -vs, and check {{user}}.
For our policies on printing, file storage, and virtual hosting, refer to the relevant documentation:
+Out of pages? Here's a suggested list of other places to print on and around campus.
+You already have an OCF account! Your username is {{account}}. If you can't remember your password, - you can reset it here. + you can reset it here. Otherwise, you can log in to access your OCF account.
If you believe this is an error, please contact us with your CalNet UID: {{calnet_uid}}. -
Please logout here.
+If you are not signing into the OCF, please log out of CalNet here.
{% endblock %} diff --git a/ocfweb/account/templates/account/register/success.html b/ocfweb/account/templates/account/register/success.html index df8a149b5..c31ac9c4b 100644 --- a/ocfweb/account/templates/account/register/success.html +++ b/ocfweb/account/templates/account/register/success.html @@ -3,7 +3,7 @@ {% block content %}Your account has successfully been created!
-You can start using any of our services. Watch out for an email from us with more information!
+You can start using any of our services. Watch out for an email from us with more information!
Thanks for flying OCF!
The Open Computing Facility (OCF) is an all-volunteer student organization dedicated to free computing for all University of California, Berkeley students, faculty, and staff.
We're passionate about open source and free software.
@@ -39,7 +43,7 @@Check out upcoming events on the OCF Newsletter.
+Check out upcoming events on the OCF calendar.
We hold weekly staff hours to provide assistance with account issues or with OCF services. Drop by to ask questions or just to hang out!
+ If you'd like to reserve the lab space for your organization's event, please review our + reservation policy and submit a request in the linked form. +
diff --git a/ocfweb/static/scss/site.scss b/ocfweb/static/scss/site.scss index b8f08adff..2b91666c7 100644 --- a/ocfweb/static/scss/site.scss +++ b/ocfweb/static/scss/site.scss @@ -15,23 +15,24 @@ $screen-lg-min: 1200px */ -$color-blue-baby: #cbe1ea; +$color-blue-baby: #c1e4f0; $color-blue-light: #f8fcfc; $color-blue: #298399; $color-gray-light: #ccc; $color-gray: #aaa; $color-green-light: #de9; +$color-purple-light: #e5e7f0; $color-yellow-light: #ffc; $color-penguin-blue: #0f4d92; $color-penguin-yellow: #ffd700; $navbar-height: 60px; -$hero-color: $color-green-light; +$hero-color: $color-blue-baby; $hero-button-color: #f7f7f7; $hero-button-color-hover: #fff; -$status-bar-color: $color-blue-baby; +$status-bar-color: $color-purple-light; $footer-top-color: $color-gray-light; $footer-bottom-color: $color-gray; @@ -70,6 +71,26 @@ code { font-family: 'IBM Plex Mono', Menlo, Consolas, monospace; } +.semibold { + font-weight: 500; +} + +.form-mini { + display: flex; + gap: 10px; + max-width: 400px; + margin-bottom: 10px; + + label { + display: none; + } + + .form-group { + margin: 0; + flex: auto; + } +} + .subtle { color: #999; diff --git a/ocfweb/templates/base.html b/ocfweb/templates/base.html index d8ccb3ba5..477d07b9f 100644 --- a/ocfweb/templates/base.html +++ b/ocfweb/templates/base.html @@ -61,6 +61,7 @@