2022-12-30 06:51:51 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Copyright © 2022 Roberto Hidalgo <nidito@un.rob.mx>
|
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/sirupsen/logrus"
|
2023-01-02 06:54:23 +00:00
|
|
|
"github.com/upper/db/v4"
|
2022-12-30 06:51:51 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func parseHour(src string) (float64, error) {
|
|
|
|
hm := strings.Split(src, ":")
|
|
|
|
if len(hm) == 1 {
|
|
|
|
return strconv.ParseFloat(hm[0], 32)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(hm) == 2 {
|
|
|
|
h, err := strconv.ParseFloat(hm[0], 32)
|
|
|
|
if err != nil {
|
|
|
|
return 0.0, err
|
|
|
|
}
|
|
|
|
m, err := strconv.ParseFloat(hm[1], 32)
|
|
|
|
if err != nil {
|
|
|
|
return 0.0, err
|
|
|
|
}
|
|
|
|
return h + (m / 60.0), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0.0, fmt.Errorf("unknown format for hour: %s", hm)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
type UserSchedule struct {
|
|
|
|
src string
|
|
|
|
days []int
|
|
|
|
hours []float64
|
|
|
|
}
|
|
|
|
|
2023-01-02 06:54:23 +00:00
|
|
|
func (d UserSchedule) MarshalDB() (any, error) {
|
2022-12-30 06:51:51 +00:00
|
|
|
return json.Marshal(d.src)
|
|
|
|
}
|
|
|
|
|
2023-01-02 06:54:23 +00:00
|
|
|
func (d UserSchedule) MarshalJSON() ([]byte, error) {
|
|
|
|
return json.Marshal(d.src)
|
|
|
|
}
|
|
|
|
|
2023-01-03 07:40:38 +00:00
|
|
|
func (d *UserSchedule) Parse() error {
|
|
|
|
for _, kv := range strings.Split(d.src, " ") {
|
2022-12-30 06:51:51 +00:00
|
|
|
kvSlice := strings.Split(kv, "=")
|
|
|
|
key := kvSlice[0]
|
|
|
|
values := strings.Split(kvSlice[1], "-")
|
|
|
|
switch key {
|
|
|
|
case "days":
|
|
|
|
from, err := strconv.Atoi(values[0])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
until, err := strconv.Atoi(values[1])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
logrus.Infof("Parsed schedule days from: %d until %d", from, until)
|
|
|
|
d.days = []int{from, until}
|
|
|
|
case "hours":
|
|
|
|
from, err := parseHour(values[0])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
until, err := parseHour(values[1])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
logrus.Infof("Parsed schedule hours from: %f until %f", from, until)
|
|
|
|
d.hours = []float64{from, until}
|
|
|
|
}
|
|
|
|
}
|
2023-01-03 07:40:38 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *UserSchedule) UnmarshalDB(value any) error {
|
|
|
|
var src string
|
|
|
|
if err := json.Unmarshal(value.([]byte), &src); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
parsed := UserSchedule{src: src}
|
|
|
|
if err := parsed.Parse(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*d = parsed
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *UserSchedule) UnmarshalJSON(value []byte) error {
|
|
|
|
parsed := UserSchedule{src: string(value)}
|
|
|
|
if err := parsed.Parse(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-30 06:51:51 +00:00
|
|
|
|
2023-01-03 07:40:38 +00:00
|
|
|
*d = parsed
|
2022-12-30 06:51:51 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sch *UserSchedule) AllowedAt(t time.Time) bool {
|
|
|
|
weekDay := int(t.Weekday())
|
|
|
|
h, m, s := t.Clock()
|
|
|
|
fractionalHour := float64(h) + (float64(m*60.0+s) / 3600.0)
|
|
|
|
|
|
|
|
logrus.Infof("Validating access at weekday %d, hour %f from rules: days=%v hours=%v at %s", weekDay, fractionalHour, sch.days, sch.hours, t.String())
|
|
|
|
if sch.days != nil {
|
|
|
|
if weekDay < sch.days[0] || weekDay > sch.days[1] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if sch.hours != nil {
|
|
|
|
if fractionalHour < sch.hours[0] || fractionalHour > sch.hours[1] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
2023-01-02 06:54:23 +00:00
|
|
|
|
|
|
|
var _ = (db.Unmarshaler(&UserSchedule{}))
|
|
|
|
var _ = (db.Marshaler(&UserSchedule{}))
|
2023-01-03 07:40:38 +00:00
|
|
|
var _ = (json.Marshaler(&UserSchedule{}))
|
|
|
|
var _ = (json.Unmarshaler(&UserSchedule{}))
|