2020-03-27 13:57:14 +00:00
package adlin
import (
"crypto/hmac"
"crypto/sha512"
2021-03-05 14:14:45 +00:00
"fmt"
2020-03-27 13:57:14 +00:00
"time"
)
type Student struct {
2021-03-04 00:04:58 +00:00
Id int64 ` json:"id" `
Login string ` json:"login" `
Time * time . Time ` json:"time" `
IP * string ` json:"ip" `
MAC * string ` json:"mac" `
AssociatedDomain * string ` json:"associated_domain,omitempty" `
DelegatedDomain * string ` json:"delegated_domain,omitempty" `
2020-03-27 13:57:14 +00:00
}
2021-03-07 11:39:38 +00:00
func GetStudents ( ) ( students [ ] * Student , err error ) {
2021-03-04 00:04:58 +00:00
if rows , errr := DBQuery ( "SELECT S.id_student, S.login, MAX(L.time), L.ip, L.mac, S.associatedDomain, S.delegatedDomain FROM students S INNER JOIN (SELECT a.id_student, a.time, a.ip, a.mac FROM student_login a INNER JOIN (SELECT id_student, MAX(time) AS time FROM student_login GROUP BY id_student) b ON a.id_student = b.id_student AND a.time = b.time) L ON S.id_student = L.id_student GROUP BY id_student" ) ; errr != nil {
2020-03-27 13:57:14 +00:00
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
2021-03-07 11:39:38 +00:00
s := & Student { }
2021-03-04 00:04:58 +00:00
if err = rows . Scan ( & s . Id , & s . Login , & s . Time , & s . IP , & s . MAC , & s . AssociatedDomain , & s . DelegatedDomain ) ; err != nil {
2020-03-27 13:57:14 +00:00
return
}
students = append ( students , s )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
2021-03-07 11:39:38 +00:00
func GetStudent ( id int ) ( s * Student , err error ) {
s = new ( Student )
2021-03-04 00:04:58 +00:00
err = DBQueryRow ( "SELECT S.id_student, S.login, MAX(L.time), L.ip, L.mac, S.associatedDomain, S.delegatedDomain FROM students S INNER JOIN (SELECT a.id_student, a.time, a.ip, a.mac FROM student_login a INNER JOIN (SELECT id_student, MAX(time) AS time FROM student_login GROUP BY id_student) b ON a.id_student = b.id_student AND a.time = b.time) L ON S.id_student = L.id_student WHERE S.id_student=?" , id ) . Scan ( & s . Id , & s . Login , & s . Time , & s . IP , & s . MAC , & s . AssociatedDomain , & s . DelegatedDomain )
2020-03-27 13:57:14 +00:00
return
}
2021-03-07 11:39:38 +00:00
func GetStudentByLogin ( login string ) ( s * Student , err error ) {
s = new ( Student )
2021-03-04 00:04:58 +00:00
err = DBQueryRow ( "SELECT S.id_student, S.login, MAX(L.time), L.ip, L.mac, S.associatedDomain, S.delegatedDomain FROM students S INNER JOIN (SELECT a.id_student, a.time, a.ip, a.mac FROM student_login a INNER JOIN (SELECT id_student, MAX(time) AS time FROM student_login GROUP BY id_student) b ON a.id_student = b.id_student AND a.time = b.time) L ON S.id_student = L.id_student WHERE login=?" , login ) . Scan ( & s . Id , & s . Login , & s . Time , & s . IP , & s . MAC , & s . AssociatedDomain , & s . DelegatedDomain )
2020-03-27 13:57:14 +00:00
return
}
func StudentExists ( login string ) bool {
var z int
err := DBQueryRow ( "SELECT 1 FROM students WHERE login=?" , login ) . Scan ( & z )
return err == nil && z == 1
}
2021-03-07 11:39:38 +00:00
func NewStudent ( login string ) ( * Student , error ) {
2020-03-27 13:57:14 +00:00
t := time . Now ( )
if res , err := DBExec ( "INSERT INTO students (login, time) VALUES (?, ?)" , login , t ) ; err != nil {
2021-03-07 11:39:38 +00:00
return nil , err
2020-03-27 13:57:14 +00:00
} else if sid , err := res . LastInsertId ( ) ; err != nil {
2021-03-07 11:39:38 +00:00
return nil , err
2020-03-27 13:57:14 +00:00
} else {
2021-03-07 11:39:38 +00:00
return & Student { sid , login , & t , nil , nil , nil , nil } , nil
2020-03-27 13:57:14 +00:00
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) GetPKey ( ) [ ] byte {
2020-03-27 13:57:14 +00:00
return hmac . New ( sha512 . New512_224 , [ ] byte ( SharedSecret ) ) . Sum ( [ ] byte ( s . Login ) )
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) Update ( ) ( int64 , error ) {
2021-03-04 00:04:58 +00:00
if res , err := DBExec ( "UPDATE students SET login = ?, time = ?, associatedDomain = ?, delegatedDomain = ? WHERE id_student = ?" , s . Login , s . Time , s . AssociatedDomain , s . DelegatedDomain , s . Id ) ; err != nil {
2020-03-27 13:57:14 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) Delete ( ) ( int64 , error ) {
2020-03-27 13:57:14 +00:00
if res , err := DBExec ( "DELETE FROM students WHERE id_student = ?" , s . Id ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
func ClearStudents ( ) ( int64 , error ) {
if res , err := DBExec ( "DELETE FROM students" ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
type UnlockedChallenge struct {
Id int64 ` json:"id,omitempty" `
IdStudent int64 ` json:"id_student" `
Challenge int ` json:"challenge,omitempty" `
2021-03-07 11:39:38 +00:00
Time * time . Time ` json:"time,omitempty" `
2020-03-27 13:57:14 +00:00
Value interface { } ` json:"value,omitempty" `
2021-03-07 11:39:38 +00:00
LastCheck * time . Time ` json:"last_check,omitempty" `
Error string ` json:"error,omitempty" `
2020-03-27 13:57:14 +00:00
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) GetStates ( ) ( ucs [ ] * UnlockedChallenge , err error ) {
2020-03-27 13:57:14 +00:00
if rows , errr := DBQuery ( "SELECT id_st, challenge, time FROM student_challenges WHERE id_student = ?" , s . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
2021-03-07 11:39:38 +00:00
u := & UnlockedChallenge { }
2020-03-27 13:57:14 +00:00
u . IdStudent = s . Id
if err = rows . Scan ( & u . Id , & u . Challenge , & u . Time ) ; err != nil {
return
}
ucs = append ( ucs , u )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) GetChallengeErrors ( ) ( ucs [ ] * ErroredChallenge , err error ) {
if rows , errr := DBQuery ( "SELECT id_st, challenge, time, error FROM student_challenge_errors WHERE id_student = ?" , s . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
u := & ErroredChallenge { }
u . IdStudent = s . Id
if err = rows . Scan ( & u . Id , & u . Challenge , & u . Time , & u . Error ) ; err != nil {
return
}
ucs = append ( ucs , u )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
func ( s * Student ) GetStatesByChallenge ( ) ( ucs [ ] * UnlockedChallenge , err error ) {
2020-03-27 13:57:14 +00:00
if rows , errr := DBQuery ( "SELECT id_st, challenge, MIN(time), value FROM student_challenges WHERE id_student = ? GROUP BY challenge, id_student" , s . Id ) ; errr != nil {
return nil , errr
} else {
defer rows . Close ( )
for rows . Next ( ) {
2021-03-07 11:39:38 +00:00
u := & UnlockedChallenge { }
2020-03-27 13:57:14 +00:00
u . IdStudent = s . Id
if err = rows . Scan ( & u . Id , & u . Challenge , & u . Time , & u . Value ) ; err != nil {
return
}
ucs = append ( ucs , u )
}
if err = rows . Err ( ) ; err != nil {
return
}
return
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) UnlockChallenge ( challenge int , value string ) ( uc * UnlockedChallenge , err error ) {
2021-03-05 14:14:45 +00:00
if uc , err = s . UnlockNewChallenge ( challenge , value ) ; err != nil {
if uc , err = s . UpdateUnlockedChallenge ( challenge , value ) ; err != nil {
return
}
}
s . RegisterChallengeError ( challenge , fmt . Errorf ( "OK" ) )
return
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) UnlockNewChallenge ( challenge int , value string ) ( * UnlockedChallenge , error ) {
2020-03-27 13:57:14 +00:00
if res , err := DBExec ( "INSERT INTO student_challenges (id_student, challenge, time, value) VALUES (?, ?, ?, ?)" , s . Id , challenge , time . Now ( ) , value ) ; err != nil {
2021-03-07 11:39:38 +00:00
return nil , err
2020-03-27 13:57:14 +00:00
} else if utid , err := res . LastInsertId ( ) ; err != nil {
2021-03-07 11:39:38 +00:00
return nil , err
2020-03-27 13:57:14 +00:00
} else {
2021-03-07 11:39:38 +00:00
now := time . Now ( )
return & UnlockedChallenge { utid , s . Id , challenge , & now , value , nil , "" } , err
2020-03-27 13:57:14 +00:00
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) UpdateUnlockedChallenge ( challenge int , value string ) ( * UnlockedChallenge , error ) {
2020-03-27 13:57:14 +00:00
if _ , err := DBExec ( "UPDATE student_challenges SET time = ?, value = ? WHERE id_student = ? AND challenge = ?" , time . Now ( ) , value , s . Id , challenge ) ; err != nil {
2021-03-07 11:39:38 +00:00
return nil , err
2020-03-27 13:57:14 +00:00
} else {
2021-03-07 11:39:38 +00:00
now := time . Now ( )
return & UnlockedChallenge { 0 , s . Id , challenge , & now , value , nil , "" } , err
2020-03-27 13:57:14 +00:00
}
}
2021-03-05 14:14:45 +00:00
type ErroredChallenge struct {
Id int64 ` json:"id,omitempty" `
IdStudent int64 ` json:"id_student" `
Challenge int ` json:"challenge,omitempty" `
Time time . Time ` json:"time" `
Error string ` json:"error,omitempty" `
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) RegisterChallengeError ( challenge int , err error ) error {
2021-03-05 14:14:45 +00:00
if _ , errr := DBExec ( "INSERT INTO student_challenge_errors (id_student, challenge, time, error) VALUES (?, ?, ?, ?)" , s . Id , challenge , time . Now ( ) , err . Error ( ) ) ; errr == nil {
return nil
} else if _ , errr := DBExec ( "UPDATE student_challenge_errors SET time = ?, error = ? WHERE id_student = ? AND challenge = ?" , time . Now ( ) , err . Error ( ) , s . Id , challenge ) ; errr != nil {
return errr
} else {
return nil
}
}
2021-03-07 11:39:38 +00:00
func ( s * Student ) RegisterAccess ( ip , mac string ) error {
2020-03-27 13:57:14 +00:00
if res , err := DBExec ( "INSERT INTO student_login (id_student, ip, mac, time) VALUES (?, ?, ?, ?)" , s . Id , ip , mac , time . Now ( ) ) ; err != nil {
return err
} else if _ , err := res . LastInsertId ( ) ; err != nil {
return err
} else {
return err
}
}