// Copyright (c) 2025 Nikolai Papin // // This file is part of the Auto Attendance app that looks for // self-attend QR-codes during lectures and opens their URLs in your // browser. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package linkvalidator import ( "net/url" "strings" "git.weirdcat.su/weirdcat/auto-attendance/internal/config" "git.weirdcat.su/weirdcat/auto-attendance/internal/logger" ) type LinkValidator interface { ValidateLink(string) (token string, ok bool) } type linkValidatorImpl struct { config *config.Config log *logger.Logger } // ValidateLink implements LinkValidator. func (v *linkValidatorImpl) ValidateLink(rawURL string) (token string, ok bool) { if rawURL == "" { v.log.Debug("Empty URL provided for validation") return "", false } parsedURL, err := url.Parse(rawURL) if err != nil { v.log.Debug("Failed to parse URL", "url", rawURL, "error", err) return "", false } if v.config.Communication.QrUrl != "" { expectedURL, err := url.Parse(v.config.Communication.QrUrl) if err == nil { if parsedURL.Scheme != expectedURL.Scheme || parsedURL.Host != expectedURL.Host || parsedURL.Path != expectedURL.Path { v.log.Debug("URL doesn't match configured QR URL pattern", "url", rawURL, "expected", v.config.Communication.QrUrl) return "", false } } } if v.config.Communication.ApiSelfApproveMethod != "" { if !strings.Contains(parsedURL.Path, v.config.Communication.ApiSelfApproveMethod) { v.log.Debug("URL doesn't contain expected API method", "url", parsedURL.Path, "expected", v.config.Communication.ApiSelfApproveMethod) return "", false } } token = parsedURL.Query().Get("token") if token == "" { v.log.Debug("URL missing token parameter", "url", rawURL) return "", false } v.log.Debug("URL validation successful", "url", rawURL) return token, true } func NewLinkValidator(config *config.Config, log *logger.Logger) LinkValidator { return &linkValidatorImpl{ config: config, log: log, } }