undated enforcement

This commit is contained in:
2026-09-18 00:06:25 +05:00
parent 47c292f4cd
commit b67f3f5999
3 changed files with 93 additions and 11 deletions
+87 -9
View File
@@ -553,8 +553,6 @@ def _clean_old_state() -> None:
] ]
continue continue
# Keep recent history instead
# of deleting everything.
dates = sorted( dates = sorted(
user_usage.keys() user_usage.keys()
) )
@@ -770,6 +768,86 @@ def evaluate_user(
or allowed_by_grant or allowed_by_grant
) )
# ---------------------------------------------------------
# DAILY USAGE ACCOUNTING
#
# The scheduler runs once every second.
#
# Only count usage when:
# 1. The user is actually logged in.
# 2. The user is inside an allowed access window.
# 3. The user still has daily allowance remaining.
#
# Temporary grants are consumed separately below.
# ---------------------------------------------------------
if (
logged_in
and inside_window
and allowance_remaining > 0
):
record_usage(
user_id,
1,
)
# Refresh the usage value immediately so
# the returned policy information reflects
# the second we just consumed.
usage_seconds += 1
allowance_remaining = max(
0,
allowance_seconds
- usage_seconds,
)
total_remaining = (
allowance_remaining
+ grant_seconds
)
# If this second consumed the final
# allowance second, the user must be
# locked during this same scheduler pass.
if allowance_remaining <= 0:
should_allow = (
grant_seconds > 0
)
# ---------------------------------------------------------
# TEMPORARY GRANT ACCOUNTING
#
# Temporary time is consumed only while the
# user is actually logged in and is being
# allowed by the temporary grant.
#
# The grant also has its own expires_at timestamp,
# so it cannot remain valid beyond its expiry.
# ---------------------------------------------------------
if (
logged_in
and grant_seconds > 0
):
consume_grant_seconds(
user_id,
1,
)
grant_seconds = max(
0,
grant_seconds - 1,
)
total_remaining = (
allowance_remaining
+ grant_seconds
)
should_allow = (
allowed_by_schedule
or grant_seconds > 0
)
try: try:
locked = is_locked( locked = is_locked(
username username
@@ -784,8 +862,6 @@ def evaluate_user(
username username
) )
# Re-check the state after
# unlocking.
if not is_locked( if not is_locked(
username username
): ):
@@ -795,9 +871,6 @@ def evaluate_user(
with _state_lock: with _state_lock:
state = load_state() state = load_state()
# The enforcement loop must
# continue even if one account
# cannot be unlocked.
_ = state _ = state
_ = exc _ = exc
@@ -831,8 +904,13 @@ def evaluate_user(
"allowance_remaining": allowance_remaining, "allowance_remaining": allowance_remaining,
"grant_seconds": grant_seconds, "grant_seconds": grant_seconds,
"total_remaining": total_remaining, "total_remaining": total_remaining,
"allowed_by_schedule": allowed_by_schedule, "allowed_by_schedule": (
"allowed_by_grant": allowed_by_grant, inside_window
and allowance_remaining > 0
),
"allowed_by_grant": (
grant_seconds > 0
),
"allowed": should_allow, "allowed": should_allow,
} }
+5 -1
View File
@@ -1,4 +1,8 @@
{ {
"usage": {}, "usage": {
"testuser1": {
"2026-09-17": 636
}
},
"temporary_grants": [] "temporary_grants": []
} }
+1 -1
View File
@@ -7,7 +7,7 @@ users:
monday: 0 monday: 0
tuesday: 0 tuesday: 0
wednesday: 0 wednesday: 0
thursday: 600 thursday: 900
friday: 0 friday: 0
saturday: 0 saturday: 0
access_windows: access_windows: