From 3ec76e4cfd95586c0d67112b733eea5bcb68b586 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Fri, 30 Dec 2022 23:52:11 +0000 Subject: [PATCH 1/5] Automatically un-vet members away for more than a year --- apiserver/apiserver/api/views.py | 21 ++++++++++++++- webclient/src/AdminMembers.js | 46 ++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/apiserver/apiserver/api/views.py b/apiserver/apiserver/api/views.py index 9ff500f..d323df9 100644 --- a/apiserver/apiserver/api/views.py +++ b/apiserver/apiserver/api/views.py @@ -196,11 +196,29 @@ class MemberViewSet(Base, Retrieve, Update): def unpause(self, request, pk=None): if not is_admin_director(self.request.user): raise exceptions.PermissionDenied() + + today = utils.today_alberta_tz() member = self.get_object() - member.current_start_date = utils.today_alberta_tz() + + difference = utils.today_alberta_tz() - member.paused_date + if difference.days > 370: # give some leeway + logging.info('Member has been away for %s days (since %s), unvetting...', difference.days, member.paused_date) + member.vetted_date = None + member.orientation_date = None + member.lathe_cert_date = None + member.mill_cert_date = None + member.wood_cert_date = None + member.wood2_cert_date = None + member.tormach_cnc_cert_date = None + member.precix_cnc_cert_date = None + member.rabbit_cert_date = None + member.trotec_cert_date = None + + member.current_start_date = today member.paused_date = None if not member.monthly_fees: member.monthly_fees = 55 + member.save() utils.tally_membership_months(member) utils.gen_member_forms(member) @@ -560,6 +578,7 @@ class DoorViewSet(viewsets.ViewSet, List): for card in cards: member = card.user.member if member.paused_date: continue + if not member.vetted_date: continue if not member.is_allowed_entry: continue active_member_cards[card.card_number] = '{} ({})'.format( diff --git a/webclient/src/AdminMembers.js b/webclient/src/AdminMembers.js index 8c6addf..37f1670 100644 --- a/webclient/src/AdminMembers.js +++ b/webclient/src/AdminMembers.js @@ -124,7 +124,7 @@ let prevAutoscan = ''; export function AdminMemberCards(props) { const { token, result, refreshResult } = props; const cards = result.cards; - const startDimmed = Boolean((result.member.paused_date || !result.member.is_allowed_entry) && cards.length); + const startDimmed = Boolean((result.member.paused_date || !result.member.is_allowed_entry || !result.member.vetted_date) && cards.length); const [dimmed, setDimmed] = useState(startDimmed); const [input, setInput] = useState({ active_status: 'card_active' }); const [error, setError] = useState(false); @@ -134,7 +134,7 @@ export function AdminMemberCards(props) { const { id } = useParams(); useEffect(() => { - const startDimmed = Boolean((result.member.paused_date || !result.member.is_allowed_entry) && cards.length); + const startDimmed = Boolean((result.member.paused_date || !result.member.is_allowed_entry || !result.member.vetted_date) && cards.length); setDimmed(startDimmed); }, [result.member]); @@ -298,7 +298,7 @@ export function AdminMemberCards(props) {

- Member paused or not allowed entry, {cards.length} card{cards.length === 1 ? '' : 's'} ignored anyway. + Member paused, unvetted or not allowed entry. {cards.length} card{cards.length === 1 ? '' : 's'} ignored anyway.

@@ -363,15 +363,45 @@ export function AdminMemberPause(props) {

Pause / Unpause Membership
-

Pause members who are inactive, former, or on vacation.

-

{result.member.paused_date ? - + result.member.vetted_date && moment().diff(moment(result.member.paused_date), 'days') > 370 ? + <> +

+ {result.member.preferred_name} has been away for more than a year and will need to be re-vetted according to our + policy. +

+

+ setTold1(v.checked)} + /> +

+

+ setTold2(v.checked)} + /> +

+ + + + : + : <> +

Pause members who are inactive, former, or on vacation.

+

Date: Tue, 3 Jan 2023 20:11:43 +0000 Subject: [PATCH 2/5] Fix object 404 exception handler logging --- apiserver/apiserver/api/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apiserver/apiserver/api/utils.py b/apiserver/apiserver/api/utils.py index 0ebb888..a4d91b7 100644 --- a/apiserver/apiserver/api/utils.py +++ b/apiserver/apiserver/api/utils.py @@ -476,7 +476,10 @@ def gen_member_forms(member): def custom_exception_handler(exc, context): response = exception_handler(exc, context) if response is not None: - logging.warning('Response: %s', json.dumps(exc.detail)) + if hasattr(exc, 'detail'): + logging.warning('Response: %s', json.dumps(exc.detail)) + else: + logging.warning('Response: %s', exc) return response def log_transaction(tx): From 02ecd49e85c113d4673231386eee683ee07a73bd Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Wed, 4 Jan 2023 18:28:14 +0000 Subject: [PATCH 3/5] Return member's name on pinball card scan --- apiserver/apiserver/api/views.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apiserver/apiserver/api/views.py b/apiserver/apiserver/api/views.py index d323df9..450c1c6 100644 --- a/apiserver/apiserver/api/views.py +++ b/apiserver/apiserver/api/views.py @@ -1326,6 +1326,21 @@ class PinballViewSet(Base): return Response(200) + @action(detail=True, methods=['get']) + def get_name(self, request, pk=None): + auth_token = request.META.get('HTTP_AUTHORIZATION', '') + if secrets.PINBALL_API_TOKEN and auth_token != 'Bearer ' + secrets.PINBALL_API_TOKEN: + raise exceptions.PermissionDenied() + + card = get_object_or_404(models.Card, card_number=pk) + member = card.user.member + + res = dict( + name=member.preferred_name + ' ' + member.last_name[0] + ) + return Response(res) + + class RegistrationView(RegisterView): serializer_class = serializers.MyRegisterSerializer From b3668025b37e0b2ed385930607d90f128c59459f Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Wed, 11 Jan 2023 18:28:43 +0000 Subject: [PATCH 4/5] Fix usages __str__ bug --- apiserver/apiserver/api/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apiserver/apiserver/api/models.py b/apiserver/apiserver/api/models.py index 6e36e48..b83fc26 100644 --- a/apiserver/apiserver/api/models.py +++ b/apiserver/apiserver/api/models.py @@ -221,7 +221,7 @@ class Usage(models.Model): device = models.CharField(max_length=64) started_at = models.DateTimeField(auto_now_add=True) finished_at = models.DateTimeField(null=True) - deleted_at = models.DateTimeField(null=True) + deleted_at = models.DateTimeField(null=True, blank=True) num_seconds = models.IntegerField() num_reports = models.IntegerField() @@ -232,7 +232,7 @@ class Usage(models.Model): MY_FIELDS = ['started_at', 'finished_at', 'user', 'num_seconds', 'should_bill'] def __str__(self): - return self.started_at + return str(self.started_at) class PinballScore(models.Model): user = models.ForeignKey(User, related_name='scores', blank=True, null=True, on_delete=models.SET_NULL) From 7ff628d195f465375b8669828cbb606db3733259 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Wed, 11 Jan 2023 18:50:53 +0000 Subject: [PATCH 5/5] Increase usage track username expiration time --- apiserver/apiserver/api/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apiserver/apiserver/api/views.py b/apiserver/apiserver/api/views.py index 450c1c6..b92c9f4 100644 --- a/apiserver/apiserver/api/views.py +++ b/apiserver/apiserver/api/views.py @@ -780,7 +780,8 @@ class StatsViewSet(viewsets.ViewSet, List): if should_count: start_new_use = not last_use or last_use.finished_at or last_use.username != username if start_new_use: - if username_isfrom_track and time.time() - track[device]['time'] > 20*60: + username_isexpired = time.time() - track[device]['time'] > 2*60*60 # two hours + if username_isfrom_track and username_isexpired: msg = 'Usage tracker problem expired username {} for device: {}'.format(username, device) utils.alert_tanner(msg) logger.error(msg)