PNG  IHDR!@ PLTE>O`jqv NKtEXtPage
db.scm - metalympiada
git clone git://metalympiada.org/
Log | Files | README | LICENSE

db.scm (7176B)


   1 (define-module (db)
   2   #:export (decrypt-user
   3             select-user
   4             select-all-users
   5             insert-user
   6             login-user
   7             select-answers
   8             select-answers-content
   9             insert-answers
  10             insert-results
  11             insert-score
  12             select-results))
  13 (use-modules (ice-9 binary-ports)
  14              (rnrs bytevectors)
  15              (srfi srfi-1)
  16              (srfi srfi-9)
  17              (srfi srfi-26)
  18              (sodium)
  19              (sqlite3))
  20 
  21 (define keyfile ".SECRET")
  22 (define SECRET_KEY
  23   (catch #t
  24     (lambda () (call-with-input-file keyfile get-bytevector-all))
  25     (lambda (key . args) (generate-key))))
  26 ;(call-with-output-file keyfile (cut put-bytevector <> SECRET_KEY))
  27 
  28 (define db (sqlite-open "meta.sqlite"))
  29 
  30 (define-record-type <user>
  31   (make-user name email password)
  32   user?
  33   (name user-name)
  34   (email user-email)
  35   (password user-password))
  36 
  37 (define (err->msg key who code errmsg)
  38     (list #f (case code
  39                    ((1299) "Niektoré povinné polia chýbajú")
  40                    ((2067) "Užívateľ s týmito údajmi už existuje")
  41                    (else (begin (display code (current-error-port))
  42                                 (display errmsg (current-error-port))
  43                                 "Niečo sa pokazilo v útrobách metaserveru! Skúste znovu")))))
  44 
  45 (define (select-user name)
  46   (let* ((stmt (sqlite-prepare db "select * from users where 'name' = ?"))
  47          (result (sqlite-map make-user stmt)))
  48         (sqlite-bind stmt 1 name)
  49         (sqlite-finalize stmt)
  50         result))
  51 
  52 (define (select-all-users)
  53   (let* ((stmt (sqlite-prepare db "select name from users"))
  54          (result (sqlite-map (cut vector-ref <> 0) stmt)))
  55         (sqlite-finalize stmt)
  56         result))
  57 
  58 (define (encrypt-user user)
  59   (base64-encode (encrypt (string->utf8 user) SECRET_KEY)))
  60 
  61 (define (decrypt-user user)
  62   (let ((decrypted (decrypt (base64-decode user) SECRET_KEY)))
  63        (if decrypted (utf8->string decrypted) #f)))
  64 
  65 (define (insert-user name email password)
  66   (catch 'sqlite-error
  67     (lambda ()
  68       (let ((stmt (sqlite-prepare db "insert into users values(?, ?, ?)")))
  69            (sqlite-bind stmt 1 name)
  70            (sqlite-bind stmt 2 email)
  71            (sqlite-bind stmt 3 (if (string? password)
  72                                    (hash-password password)
  73                                    #f))
  74            (sqlite-step stmt)
  75            (sqlite-finalize stmt)
  76            (list #t (encrypt-user name))))
  77     err->msg))
  78 
  79 (define (login-user name password)
  80   (catch 'sqlite-error
  81     (lambda ()
  82       (let ((stmt (sqlite-prepare db "select password from users where name = ?")))
  83            (sqlite-bind stmt 1 name)
  84            (let ((row (sqlite-step stmt)))
  85                 (sqlite-finalize stmt)
  86                 (if (and row (verify-password password (vector-ref row 0)))
  87                     (list #t (encrypt-user name))
  88                     (list #f "Meno alebo heslo nie je správne")))))
  89     err->msg))
  90 
  91 (define (insert-answers answers user round)
  92   (catch 'sqlite-error
  93     (lambda ()
  94       (let* ((stmt-text (string-append (fold (lambda (i so-far)
  95                                                      (string-append so-far ", (?,?,?,?)"))
  96                                              "insert into answers (name, round, problem, content) values(?,?,?,?)"
  97                                              (iota (- (length answers) 1)))
  98                                         " on conflict (name, round, problem) do update set content=excluded.content"))
  99              (stmt (sqlite-prepare db stmt-text)))
 100             (for-each (lambda (a i) (begin (sqlite-bind stmt (+ (* i 4) 1) user)
 101                                            (sqlite-bind stmt (+ (* i 4) 2) round)
 102                                            (sqlite-bind stmt (+ (* i 4) 3) (+ i 1))
 103                                            (sqlite-bind stmt (+ (* i 4) 4) a)))
 104                       answers
 105                       (iota (length answers)))
 106             (sqlite-step stmt)
 107             (sqlite-finalize stmt)
 108             (list #t)))
 109     err->msg))
 110 
 111 (define (insert-results results user round)
 112   (catch 'sqlite-error
 113     (lambda ()
 114       (let* ((stmt-text (string-append (fold (lambda (i so-far)
 115                                                      (string-append so-far ", (?,?,?,?)"))
 116                                              "insert into answers (name, round, problem, correct) values(?,?,?,?)"
 117                                              (iota (- (length results) 1)))
 118                                         " on conflict (name, round, problem) do update set correct=excluded.correct"))
 119              (stmt (sqlite-prepare db stmt-text)))
 120             (for-each (lambda (a i) (begin (sqlite-bind stmt (+ (* i 4) 1) user)
 121                                            (sqlite-bind stmt (+ (* i 4) 2) round)
 122                                            (sqlite-bind stmt (+ (* i 4) 3) (+ i 1))
 123                                            (sqlite-bind stmt (+ (* i 4) 4) a)))
 124                       results
 125                       (iota (length results)))
 126             (sqlite-step stmt)
 127             (sqlite-finalize stmt)
 128             (list #t)))
 129     err->msg))
 130 
 131 (define (select-answers user round)
 132   (catch 'sqlite-error
 133     (lambda ()
 134       (let* ((stmt-text "select content, correct from answers where name=? and round=? order by problem")
 135              (stmt (sqlite-prepare db stmt-text)))
 136             (sqlite-bind stmt 1 user)
 137             (sqlite-bind stmt 2 round)
 138             (let ((res (sqlite-map identity stmt)))
 139                  (sqlite-finalize stmt)
 140                  (if (null? res) #f res))))
 141     (lambda (key who code msg) (begin (display msg (current-error-port)) #f))))
 142 
 143 (define (select-answers-content user round)
 144   (catch 'sqlite-error
 145     (lambda ()
 146       (let* ((stmt-text "select content from answers where name=? and round=? order by problem")
 147              (stmt (sqlite-prepare db stmt-text)))
 148             (sqlite-bind stmt 1 user)
 149             (sqlite-bind stmt 2 round)
 150             (let ((res (sqlite-map (cut vector-ref <> 0) stmt)))
 151                  (sqlite-finalize stmt)
 152                  (if (null? res) #f res))))
 153     (lambda (key who code msg) (begin (display msg (current-error-port)) #f))))
 154 
 155 (define (select-results round)
 156   (catch 'sqlite-error
 157     (lambda ()
 158       (let* ((stmt-text "select name, score from results where round=? order by score desc")
 159              (stmt (sqlite-prepare db stmt-text)))
 160             (sqlite-bind stmt 1 round)
 161             (let ((res (sqlite-map identity stmt)))
 162                  (sqlite-finalize stmt)
 163                  (if (null? res) #f res))))
 164     (lambda (key who code msg) (begin (display msg (current-error-port)) #f))))
 165 
 166 (define (insert-score name round score)
 167   (catch 'sqlite-error
 168     (lambda ()
 169       (let ((stmt (sqlite-prepare db "insert into results values(?, ?, ?) on conflict(name, round) do update set score=excluded.score")))
 170            (sqlite-bind stmt 1 name)
 171            (sqlite-bind stmt 2 round)
 172            (sqlite-bind stmt 3 score)
 173            (sqlite-step stmt)
 174            (sqlite-finalize stmt)))
 175     err->msg))
#tIDATxo#Gvǫ,nV XD8zAL{R {/c`( hs8jespQLHrZ,=K=kz ^u^5% Hz^WtSѦ tC@=6f0 <E1:fr6(6#ou;AbQ>ѩ$ 失 !2'o`L ^ Gr82&cIR֤:ђ:T 5hfqR6d`a6\LFkA kGIB֍O$<3P<4|+~>,X׌#sy A> הE%ah7OS Ԁ&`0xTINkњ ͩ녁`pxF嚀 ż(N^=m܋@=Rq:w]# 2+ZB%&?r:+h#`A6I ,nt`@*C>Im|#h,V>2IVvHquRta@85Y59!n uA}Vٵ=ՃgVqۆ0i<p }As;1e+c5@,GbS(zXNs )nr8nK*Ԥ-f xd*F*~K.5 a؞ؕ0wMmJ|gUVPZ _! ͘8}#-Hk*̮h,Q)TN%+#߁Ԅ'Kjdۣ(a"xZ@6n+hg04I،VH%Vx>qIJ|WWzBxTEJM8J>%͕=l z+,XS(N J+iI㪖K 3 vRp ;K\\۵:E0t,.tif#URtf҉Dvv3_:lBS ޖ@o!trX<(M@{mr9@ۗX2"4SK..a  =0) "8R,7A$ʇM+mI%e>ja%CvS؏Zy|8h#dmz2%HoTɨ YkH.$hzy/@.ht#@uV@fխKA PƯw#]:~ICYk;nX[=MY@7%K'5`#ԶO}>,G.5:p ~S<Z҉_π_:7w5>7wk}|MLk C8޺w loj-Gk7P,8X8Ј)FXsq0.tpoJq(yy=ބV1ړ'(Pk7~ݝr~ q,UP `>;ɽQ|陟O)/<@va7d +sУ8(j\a\A\_(}oyC"FѼx͹Tս:hw4+,Lb6L0V;n6wX+8_|e洨!}-\|7(RGc]-76Y9EYB1عv.b?lG$%4v)*,# CIA^Yu\gǀDGӷ5<|>d3_fOcw[B wZɱqhX mWR3%Q OU=e;eҝ,_5F|R^ hWSPAf 4yTU])H>iҰ?nf ~s҂>oF ̬Ŗԫ0` bI0bz0VÄu?mVz_|,@"Ah7߅fgxr񯸚%r[ c560DX0.Vu{O; c5L1g`otzutpFNkH-\Ԭpp-(-HDŽdtjp3 A.0:VT w0$(>Ƣ#ہI46\LcpqGD$*21Melކ<ؙ luhLM/s=)q(a}#.WI2Bvr4Pz"Pha\ bѦ$*_ƀ$0]4ð@f* sXgڅx0߁H\A:Q#r@s $HWFC Wz.rh'fHyHƦh!F(>EMP m;fyd-Я!60|gG7&Q]7D/w~ \&v ሎܺQZ H r,*Jl#‘N/y=:¾;ҁkv^]q?`aEiC#9`\z+#&*2(.!c*[cѱQe`wa6wrX8VWu,&xľ{ IUBґ>'C= ]G7IUe b(ϵ֮ 3<ɰHhWK0H`wH9)EWH=|ni`h< Zmb? !%]I|](g Ub5ӿ/0\I3@ʉo VgKV=(zm='1nڲJ1ٍ pUHSl9M2=I% [@-, er0@@ܖ'#TxRn x2@1"ƜpxDB jc|K)&`~[{г/O9f~#wͱB 1˂vSlfM8*ƦI s\u\=tǓB5\6^SŚh4'3cH*jVGΗ6$A <P]FI}ᲶX3# Li+f3#J軶3:=gWYe~ hL^Gâ"| H#yc_6'є9PCpLx /Lҕ\}3@fFf "cx/*/D?j gmXb8\VPAEv=IHfޏ$7 t c~si[nSuPk10ϯ* ^ /a@_A@*,9*D& {H].Y}s|J[?Yg_u˅) k. ~^"/f8^{2jۮNF.دh"+^HagiNcяϯG[od.βd;.d.O܃=[Rp/n=hMGv8+p%'Qۜ<4j_a̶[ m28AQ{5teJKl]̳zꖧhf"G^6nb_fO)MsA fr/LIENDB`