diff --git a/.gitignore b/.gitignore index 0bac094..284942e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ newexampleschema *.swp run_auth.py *.sq3 +authlibs/logs/static/kioskimages/* +*.acl +backups/ diff --git a/README.md b/README.md index 0057a07..4ee6483 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,9 @@ Some rough documentation as of December 2018. `pip install google-oauth` `sudo pip install sqlalchemy_utils` +For Covid-19 video kiosk compliance reporting script +`sudo apt install ffmpeg` + ## Creating stub database `sqlite3 makeit.db < schema.sql` @@ -106,7 +109,15 @@ In a non-production enviroment, allow non-SSL OAuth with: `python authserver.py` -This should start a server on `0.0.0.0:5000` which you can get to via browser or use the API calls. The default user/password is admin/admin (configured in .ini file). +This should start a server on `0.0.0.0:5000` which you can get to via browser or use the API calls. The default user/password is admin/admin (configured in .ini file) - but this won't be present if you're using a production database. + +There are a few things you generally want to do in a local debug environment: + +* In `makeit.ini` set `Deployment:` to something other than `Production` (This will make your GUI look different than production) +* In `makeit.ini` set `Logins: all` +* In `makeit.ini` set `DefaultLogin:` to `local`. THis will let you login with local credentials when `oauth` isn't working +* Do `python authserver.py --command addadmin admin admin` to add an admin account w/ password Admin (if there isn't one - like from a live database) +* Add `local.makeitlabs.com` to your `/etc/hosts` to resolve to localhost. Use that address (in we browser) to access the server. This name is whitelisted in the Oauth rules, so Oauth will be able to redirect to it (i.e. your local server) ## Fix for newer versions of Flask library @@ -125,7 +136,6 @@ Change the import line in `authserver.py` to: from flask_login import LoginManager, UserMixin, login_required, current_user, login_user, logout_user ``` - ## Using the CLI: CLI is needed for some zero-start conditions - like assigning privilieges, or (non-oauth-login) passwords @@ -155,6 +165,8 @@ You will want to run `nightly.py` on some nightly cron job. It will: To help restore backups - you can use the `restore.py` helper script +For an example crontab - see `crontab.txt` + # Update/Deploy @@ -162,14 +174,8 @@ To help restore backups - you can use the `restore.py` helper script Verify that `authserver.wsgi` is set for your appopriate deploy! (See `authserver.wsgi.EXAMPLE` for example) -### v1.0.5 Schema Update +In `makeit.ini` set a defualt door lockout message with `LockoutMessage` in the `General` section. This should not be present for normal deployments, but might want to say `Covid-19 Training Required` if appropriate. -``` -begin transaction; -ALTER TABLE nodes ADD strength INTEGER; -ALTER TABLE nodes ADD last_update DATETIME; -commit; -``` ### If you care about getting Slack training invites working: diff --git a/authlibs/api/api.py b/authlibs/api/api.py index e220123..83150f4 100644 --- a/authlibs/api/api.py +++ b/authlibs/api/api.py @@ -14,6 +14,8 @@ import base64 import random,string import tempfile +import subprocess + # You must call this modules "register_pages" with main app's "create_rotues" blueprint = Blueprint("api", __name__, template_folder='templates', static_folder="static",url_prefix="/api") @@ -378,6 +380,19 @@ def api_v1_kiosklog(): authutil.log(e,member_id=m.id,message=imagename,commit=0) db.session.commit() + try: + cam_slackchan = current_app.config['globalConfig'].Config.get('cameras','slackchan') + s = subprocess.Popen(['/home/bkg/covid-mask-detector/covid-mask-detector/testone.py',imagecode],stdout=subprocess.PIPE) + txt = s.stdout.read().strip() + res = s.wait() + if (res != 0): + url="https://auth.makeitlabs.com"+url_for("logs.kioskentry",ke=imagecode) + res = send_slack_message( + "#project-covid-kiosk", + ":alert: {0} {1} at kiosk {2}".format(m.member,txt,url) + ) + except BaseException as e: + logger.error("Kiosk mask check error {0}".format(e)) try: url="" if imagecode: diff --git a/authlibs/google_user_auth.py b/authlibs/google_user_auth.py index 2d78679..e209c0d 100644 --- a/authlibs/google_user_auth.py +++ b/authlibs/google_user_auth.py @@ -94,7 +94,7 @@ def google_logged_in(blueprint, token): member=email.split("@")[0] logger.debug("Google auth RESP for {0} {1}".format(email,member)) if not email.endswith("@makeitlabs.com"): - flash("Not a MakeIt Labs account",'warning') + flash("Not a MakeIt Labs account - You must log in with your @makeitlabs.com email address",'warning') logger.error("Not a MakeIt Labs account "+str(email)) return redirect(url_for('empty')) #query = Member.query.filter_by(Member.member.ilike(member)) @@ -110,7 +110,7 @@ def google_logged_in(blueprint, token): if len(user) ==0: flash("Error - No account found - please seek assistance",'warning') - logger.error("No account matchin %s for GUI login" % email) + logger.error("No account matching %s for GUI login" % email) return redirect(url_for('empty')) user = user[0] diff --git a/authlibs/logs/logs.py b/authlibs/logs/logs.py index e9cdb9e..e4e10d5 100644 --- a/authlibs/logs/logs.py +++ b/authlibs/logs/logs.py @@ -394,6 +394,9 @@ def kioskentry(ke): ke = ke.replace("/","") ke = ke.replace(".","") ke = ke.replace("kioskimages:","") + if not current_user.is_arm() and (len(current_user.effective_roles()) == 0): + flash("Not authorized for this page","warning") + return redirect_url_for("index") return render_template('kiosk_entry.html',entry=ke) blueprint.route('/large.csv') diff --git a/authlibs/members/members.py b/authlibs/members/members.py index 4f567d4..dfaea01 100644 --- a/authlibs/members/members.py +++ b/authlibs/members/members.py @@ -835,8 +835,11 @@ def getDoorAccess(id): if r: acc = accesslib.access_query(r.id,member_id=id,tags=False) acc = acc.first() - if not acc: - return ("No Access Record (Needs orientation?)",False,None) + if not acc: + msg = "No Access Record (Needs orientation?)" + if current_app.config['globalConfig'].Config.has_option('General','LockoutMessage'): + msg = current_app.config['globalConfig'].Config.get('General','LockoutMessage') + return (msg,False,None) acc=accesslib.accessQueryToDict(acc) (warning,allowed) = accesslib.determineAccess(acc,"Door access pending orientation") diff --git a/authlibs/membership.py b/authlibs/membership.py index 4f8869c..6ca35f8 100644 --- a/authlibs/membership.py +++ b/authlibs/membership.py @@ -229,6 +229,7 @@ def createMissingMemberAccounts(members,isTest=True,searchGoogle=False): password = "%s%d%d" % (nameparts['last'],random.randint(1,100000),len(nameparts['last'])) try: google.createUser(nameparts['first'],nameparts['last'],m.member,m.alt_email,password) + m.email=m.member.lower()+"@makeitlabs.com" google.sendWelcomeEmail(m.member,password,m.alt_email) msg = "Created new Google account for %s %s" % (m.member,m.alt_email) logger.warn(msg) diff --git a/authlibs/resources/resources.py b/authlibs/resources/resources.py index 51a7b5d..557699b 100644 --- a/authlibs/resources/resources.py +++ b/authlibs/resources/resources.py @@ -344,6 +344,13 @@ def resource_showusers(resource): (lu1,lu2,lu3) = ago.ago(mid_to_lastuse[x[1]],now) lu2 += " ago" sorttime = mid_to_lastuse[x[1]] + else: + # Maybe it's a door? + d = Logs.query.filter((Logs.event_type == eventtypes.RATTBE_LOGEVENT_MEMBER_ENTRY_ALLOWED.id) & (Logs.resource_id == res_id) & (Logs.member_id == x[1])).order_by(Logs.time_logged.desc()).limit(1).one_or_none() + if d: + (lu1,lu2,lu3) = ago.ago(d.time_logged,now) + lu2 += " ago" + sorttime = d.time_logged accrec.append({'member_id':x[1],'member':x[2],'level':level, 'sortlevel':int(x[3]), 'sorttime':sorttime, diff --git a/authlibs/resources/templates/resource_edit.html b/authlibs/resources/templates/resource_edit.html index 2ef3ab0..9a86399 100644 --- a/authlibs/resources/templates/resource_edit.html +++ b/authlibs/resources/templates/resource_edit.html @@ -3,6 +3,7 @@

Edit Resource

+ Members Usage Graphs Usage Reports Maintenance diff --git a/authlibs/training/training.py b/authlibs/training/training.py index d869e1c..5e4ebbf 100644 --- a/authlibs/training/training.py +++ b/authlibs/training/training.py @@ -29,7 +29,7 @@ def training(): ar['desc'] = 'Authorization was revoked' ar['status'] = 'cannot' elif ma.level >0: - ar['desc'] = 'You\'r are a Resource Manager' + ar['desc'] = 'You are a Resource Manager' ar['status'] = 'already' else: #User has no access - can they train? diff --git a/authlibs/waivers/templates/relate.html b/authlibs/waivers/templates/relate.html new file mode 100644 index 0000000..2d5d2ad --- /dev/null +++ b/authlibs/waivers/templates/relate.html @@ -0,0 +1,75 @@ +{% extends "layout_bootstrap.html" %} +{% block body %} +

To assign a waiver to a member - select to appropriate radio boxes for each, then click "assign"

+
+
+

Unassigned Waivers

+
+
+ + +
+
+

Enter a phrase in the search box

+ + + + + + + + + {% for s in waivers %} + + + + + + {% if s.waivertype in waiverTypes %} + + {% else %} + + {% endif %} + + + {% endfor %} +
NameEmailCreatedWaiver IDWaiver Type
{{ s.lastname }}, {{s.firstname}}{{ s.email }}{{ s.created_date }}{{ s.waiver_id }}{{ waiverTypes[s.waivertype] }}??? Assign to...
+ +
+
+

Attach to Member:

+
+ {% with add_radiobuttons=1 %} + {% include 'userlist.html' %} + {% endwith %} +
+
+ +{% endblock %} diff --git a/authlibs/waivers/templates/waivers.html b/authlibs/waivers/templates/waivers.html index f800909..f831633 100644 --- a/authlibs/waivers/templates/waivers.html +++ b/authlibs/waivers/templates/waivers.html @@ -6,7 +6,8 @@
Waiver Data
{% if current_user.privs("Useredit") or current_user.privs("Finance") %} - Update Waiver Data (May take a while) + Update Waiver Data (May take a while) + Assign Waivers {% endif %}

Show Waivers: