0 package db
1
2 import (
3 "database/sql"
4 "errors"
5 "gemigit/config"
6 "log"
7 "os"
8 "strconv"
9 "time"
10
11 _ "github.com/mattn/go-sqlite3"
12 _ "github.com/go-sql-driver/mysql"
13 )
14
15 type Repo struct {
16 RepoID int
17 UserID int
18 Username string
19 Name string
20 Date int
21 IsPublic bool
22 Description string
23 }
24
25 type User struct {
26 ID int
27 Name string
28 Description string
29 Registration int
30 Connection time.Time
31 Signature string
32 }
33
34 type Group struct {
35 GroupID int
36 Name string
37 Description string
38 }
39
40 type Member struct {
41 Name string
42 UserID int
43 }
44
45 type Access struct {
46 RepoID int
47 GroupID int
48 UserID int
49 Name string
50 Privilege int
51 }
52
53 var users = make(map[string]User)
54 var unixTime string
55
56 func userAlreadyExist(username string) (bool, error) {
57 rows, err := db.Query(
58 "SELECT * FROM user WHERE UPPER(name) LIKE UPPER(?)",
59 username)
60 if err != nil {
61 return true, err
62 }
63 defer rows.Close()
64 if rows.Next() {
65 return true, nil
66 }
67 return false, nil
68 }
69
70 func (user *User) repoAlreadyExist(repo string) (error) {
71 rows, err := db.Query(
72 "SELECT * FROM repo WHERE UPPER(name) LIKE UPPER(?)" +
73 " AND UPPER(userID) LIKE UPPER(?)",
74 repo, user.ID)
75 if err != nil {
76 return err
77 }
78 defer rows.Close()
79 if rows.Next() {
80 return errors.New(
81 "Repository with the same name already exist")
82 }
83 return nil
84 }
85
86 func groupAlreadyExist(group string) (error) {
87 rows, err := db.Query(
88 "SELECT * FROM groups WHERE UPPER(name) LIKE UPPER(?)",
89 group)
90 if err != nil {
91 return err
92 }
93 defer rows.Close()
94 if rows.Next() {
95 return errors.New(
96 "A group with the same name already exist")
97 }
98 return nil
99 }
100
101 var db *sql.DB
102
103 func Init(dbType string, path string, create bool) error {
104
105 if !create && dbType == "sqlite3" {
106 file, err := os.Open(path)
107 if os.IsNotExist(err) {
108 file, err := os.Create(path)
109 if err != nil {
110 return err
111 }
112 file.Close()
113 log.Println("Creating database " + path)
114 create = true
115 } else {
116 file.Close()
117 log.Println("Loading database " + path)
118 }
119 }
120
121 var err error
122 db, err = sql.Open(dbType, path)
123 if err != nil {
124 return err
125 }
126 err = db.Ping()
127 if err != nil {
128 return err
129 }
130 unixTime = "UNIX_TIMESTAMP()"
131 if config.Cfg.Database.Type == "sqlite3" {
132 unixTime = "strftime('%s', 'now')"
133 }
134 if create {
135 return createTable(db)
136 }
137 return nil
138 }
139
140 func Close() error {
141 return db.Close()
142 }
143
144 func createTable(db *sql.DB) error {
145 autoincrement := "AUTO_INCREMENT"
146 if config.Cfg.Database.Type == "sqlite3" {
147 autoincrement = "AUTOINCREMENT"
148 }
149
150 userTable := `CREATE TABLE user (
151 userID INTEGER NOT NULL PRIMARY KEY ` + autoincrement + `,
152 name TEXT UNIQUE NOT NULL,
153 password TEXT,
154 description TEXT DEFAULT "",
155 creation INTEGER NOT NULL
156 );`
157
158 groupTable := `CREATE TABLE groups (
159 groupID INTEGER NOT NULL PRIMARY KEY ` + autoincrement + `,
160 owner INTEGER NOT NULL,
161 name TEXT UNIQUE NOT NULL,
162 description TEXT DEFAULT "",
163 creation INTEGER NOT NULL
164 );`
165
166 memberTable := `CREATE TABLE member (
167 groupID INTEGER NOT NULL,
168 userID INTEGER NOT NULL
169 );`
170
171 certificateTable := `CREATE TABLE certificate (
172 userID INTEGER NOT NULL,
173 hash TEXT UNIQUE NOT NULL
174 );`
175
176 accessTable := `CREATE TABLE access (
177 repoID INTEGER NOT NULL,
178 groupID INTEGER,
179 userID INTEGER,
180 privilege INTEGER NOT NULL
181 );`
182
183 repoTable := `CREATE TABLE repo (
184 repoID INTEGER NOT NULL PRIMARY KEY ` + autoincrement + `,
185 userID INTEGER NOT NULL,
186 name TEXT NOT NULL,
187 description TEXT DEFAULT "",
188 creation INTEGER NOT NULL,
189 public INTEGER DEFAULT 0
190 );`
191
192 _, err := db.Exec(userTable)
193 if err != nil {
194 return err
195 }
196 log.Println("Users table created")
197
198 _, err = db.Exec(groupTable)
199 if err != nil {
200 return err
201 }
202 log.Println("Groups table created")
203
204 _, err = db.Exec(memberTable)
205 if err != nil {
206 return err
207 }
208 log.Println("Member table created")
209
210 _, err = db.Exec(certificateTable)
211 if err != nil {
212 return err
213 }
214 log.Println("Certificate table created")
215
216 _, err = db.Exec(accessTable)
217 if err != nil {
218 return err
219 }
220 log.Println("Access table created")
221
222 _, err = db.Exec(repoTable)
223 if err != nil {
224 return err
225 }
226 log.Println("Repositories table created")
227
228 return nil
229 }
230
231 func CheckAuth(username string, password string) (error) {
232 rows, err := db.Query("SELECT name, password FROM user " +
233 "WHERE UPPER(name) LIKE UPPER(?)",
234 username)
235 if err != nil {
236 return err
237 }
238 defer rows.Close()
239 if rows.Next() {
240 var dPassword string
241 var dName string
242 err = rows.Scan(&dName, &dPassword)
243 if err != nil {
244 return err
245 }
246 if checkPassword(password, dPassword) {
247 return nil
248 }
249 }
250 return errors.New("invalid credential")
251 }
252
253 func FetchUser(username string, signature string) (User, error) {
254 query := "SELECT userID, name, description, creation " +
255 "FROM user WHERE UPPER(name) LIKE UPPER(?)"
256 rows, err := db.Query(query, username)
257 if err != nil {
258 return User{}, err
259 }
260 defer rows.Close()
261 next := rows.Next()
262 if !next {
263 return User{}, errors.New("User not found")
264 }
265 var u = User{}
266 if config.Cfg.Ldap.Enabled {
267 err = rows.Scan(&u.ID,
268 &u.Name,
269 &u.Description,
270 &u.Registration)
271 } else {
272 err = rows.Scan(&u.ID,
273 &u.Name,
274 &u.Description,
275 &u.Registration)
276 }
277 if err != nil {
278 return User{}, err
279 }
280 u.Connection = time.Now()
281 u.Signature = signature
282 return u, nil
283 }
284
285 func Register(username string, password string) error {
286
287 if !config.Cfg.Ldap.Enabled {
288 if err := isPasswordValid(password); err != nil {
289 return err
290 }
291 }
292
293 if err := isNameValid(username); err != nil {
294 return err
295 }
296
297 if exist, err := userAlreadyExist(username); exist || err != nil {
298 if err != nil {
299 return err
300 }
301 return errors.New("this name is already taken")
302 }
303
304 if !config.Cfg.Ldap.Enabled {
305 hash, err := hashPassword(password)
306 if err != nil {
307 return err
308 }
309
310 _, err = db.Exec("INSERT INTO user(name,password,creation) " +
311 "VALUES(?, ?, " + unixTime + ");",
312 username, hash)
313 if err != nil {
314 return err
315 }
316 return nil
317 }
318 _, err := db.Exec("INSERT INTO user(name,creation) " +
319 "VALUES(?, " + unixTime + ")", username)
320 if err != nil {
321 return err
322 }
323 return nil
324 }
325
326 func (user User) CreateRepo(repo string, signature string) error {
327 if err := user.VerifySignature(signature); err != nil {
328 return err
329 }
330
331 if err := isRepoNameValid(repo); err != nil {
332 return err
333 }
334
335 err := user.repoAlreadyExist(repo)
336 if err != nil {
337 return err
338 }
339
340 _, err = db.Exec("INSERT INTO repo " +
341 "(userID, name, creation, public, description) " +
342 "VALUES(?, ?, " + unixTime + ", 0, \"\")",
343 user.ID, repo)
344 if err != nil {
345 return err
346 }
347
348 return nil
349 }
350
351 func (user User) CreateGroup(group string, signature string) error {
352 if err := user.VerifySignature(signature); err != nil {
353 return err
354 }
355
356 if err := isGroupNameValid(group); err != nil {
357 return err
358 }
359
360 err := groupAlreadyExist(group)
361 if err != nil {
362 return err
363 }
364
365 rows, err := db.Exec("INSERT INTO groups " +
366 "(owner, name, description, creation) " +
367 "VALUES(?, ?, \"\", " + unixTime + ")",
368 user.ID, group)
369 if err != nil {
370 return err
371 }
372
373 groupID, err := rows.LastInsertId()
374 if err != nil {
375 return err
376 }
377
378 _, err = db.Exec("INSERT INTO member (groupID, userID) " +
379 "VALUES(?, ?)", groupID, user.ID)
380 if err != nil {
381 return err
382 }
383
384 return nil
385 }
386
387 func GetUserID(name string) (int, error) {
388 query := "SELECT userID FROM user WHERE UPPER(?) = UPPER(name);"
389 rows, err := db.Query(query, name)
390 if err != nil {
391 return -1, err
392 }
393 defer rows.Close()
394 if !rows.Next() {
395 return -1, errors.New("User not found")
396 }
397 var id int
398 err = rows.Scan(&id)
399 if err != nil {
400 return -1, err
401 }
402 return id, nil
403 }
404
405 func GetRepoID(repo string, userID int) (int, error) {
406 rows, err := db.Query("SELECT repoID FROM repo " +
407 "WHERE UPPER(?) = UPPER(name) AND userID = ?",
408 repo, userID)
409 if err != nil {
410 return -1, err
411 }
412 defer rows.Close()
413 if !rows.Next() {
414 return -1, errors.New("Repository not found")
415 }
416 var id int
417 err = rows.Scan(&id)
418 if err != nil {
419 return -1, err
420 }
421 return id, nil
422 }
423
424 func GetGroupDesc(name string) (string, error) {
425 query := "SELECT description FROM groups WHERE UPPER(?) = UPPER(name);"
426 rows, err := db.Query(query, name)
427 if err != nil {
428 return "", err
429 }
430 defer rows.Close()
431 if !rows.Next() {
432 return "", errors.New("Group not found")
433 }
434 var desc string
435 err = rows.Scan(&desc)
436 if err != nil {
437 return "", err
438 }
439 return desc, nil
440 }
441
442 func GetGroupID(name string) (int, error) {
443 query := "SELECT groupID FROM groups WHERE UPPER(?) = UPPER(name);"
444 rows, err := db.Query(query, name)
445 if err != nil {
446 return -1, err
447 }
448 defer rows.Close()
449 if !rows.Next() {
450 return -1, errors.New("Group not found")
451 }
452 var id int
453 err = rows.Scan(&id)
454 if err != nil {
455 return -1, err
456 }
457 return id, nil
458 }
459
460 func IsInGroup(userID int, groupID int) (error) {
461 query := "SELECT * FROM member WHERE userID=? AND groupID=?"
462 rows, err := db.Query(query, userID, groupID)
463 if err != nil {
464 return err
465 }
466 defer rows.Close()
467 if rows.Next() {
468 return errors.New("The user is already in the group")
469 }
470 return nil
471 }
472
473 func AddUserToGroup(group string, user string) error {
474 id, err := GetGroupID(group)
475 if err != nil {
476 return err
477 }
478 userID, err := GetUserID(user)
479 if err != nil {
480 return err
481 }
482 if err = IsInGroup(userID, id); err != nil {
483 return err
484 }
485 _, err = db.Exec("INSERT INTO member (groupID, userID) " +
486 "VALUES(?, ?)", id, userID)
487 if err != nil {
488 return err
489 }
490 return nil
491 }
492
493 func DeleteMember(user int, group int) error {
494 statement, err := db.Exec("DELETE FROM member " +
495 "WHERE userID = ? AND groupID = ?",
496 user, group)
497 if err != nil {
498 return err
499 }
500 rows, err := statement.RowsAffected()
501 if err != nil {
502 return err
503 }
504 if rows < 1 {
505 return errors.New("The user is not a member of the group")
506 }
507 return nil
508 }
509
510 func SetGroupDescription(group int, desc string) error {
511 _, err := db.Exec("UPDATE groups SET description = ? " +
512 "WHERE groupID = ?", desc, group)
513 if err != nil {
514 return err
515 }
516 return nil
517 }
518
519 func DeleteGroup(group int) error {
520 statement, err := db.Exec("DELETE FROM groups " +
521 "WHERE groupID = ?", group)
522 if err != nil {
523 return err
524 }
525 rows, err := statement.RowsAffected()
526 if err != nil {
527 return err
528 }
529 if rows < 1 {
530 return errors.New("There's no such group")
531 }
532 statement, err = db.Exec("DELETE FROM member " +
533 "WHERE groupID = ?", group)
534 if err != nil {
535 return err
536 }
537 return nil
538 }
539
540 func DeleteUser(username string) error {
541 statement, err := db.Exec("DELETE FROM repo " +
542 "WHERE userID in " +
543 "(SELECT userID FROM user " +
544 "where UPPER(name) LIKE UPPER(?))",
545 username)
546 if err != nil {
547 return err
548 }
549 rows, err := statement.RowsAffected()
550 if err != nil {
551 return err
552 }
553 statement, err = db.Exec("DELETE FROM user WHERE name=?", username)
554 if err != nil {
555 return err
556 }
557 rows, err = statement.RowsAffected()
558 if err != nil {
559 return err
560 }
561 if rows < 1 {
562 return errors.New("user " + username + " not found")
563 }
564 return nil
565 }
566
567 func (user User) DeleteRepo(repo string, signature string) error {
568 if err := user.VerifySignature(signature); err != nil {
569 return err
570 }
571 statement, err := db.Exec("DELETE FROM repo WHERE name=? AND userID=?",
572 repo, user.ID)
573 if err != nil {
574 return err
575 }
576 rows, err := statement.RowsAffected()
577 if err != nil {
578 return err
579 }
580 if rows != 1 {
581 return errors.New(strconv.Itoa(int(rows)) +
582 " deleted instead of only one")
583 }
584 return nil
585 }
586
587 func SetUser(signature string, user User) error {
588 _, err := db.Exec("INSERT INTO certificate (userID, hash) " +
589 "VALUES (?, ?)", user.ID, signature)
590 if err != nil {
591 log.Println(err.Error())
592 return err
593 }
594 user.Signature = signature
595 users[signature] = user
596 return nil
597 }
598
599 func GetUser(signature string) (User, bool) {
600 user, b := users[signature]
601 // should update description
602 if b {
603 return user, b
604 }
605 rows, err := db.Query("SELECT a.userID, name, description, creation " +
606 "FROM user a INNER JOIN certificate b ON " +
607 "a.userID = b.userID WHERE hash = ?", signature)
608 if err != nil {
609 return User{}, false
610 }
611 defer rows.Close()
612 if !rows.Next() {
613 return User{}, false
614 }
615 err = rows.Scan(&user.ID, &user.Name, &user.Description,
616 &user.Registration)
617 if err != nil {
618 return User{}, false
619 }
620 user.Signature = signature
621 users[signature] = user
622 return user, true
623 }
624
625 func GetPublicUser(name string) (User, error) {
626 rows, err := db.Query("SELECT userID, name, description, creation " +
627 "FROM user WHERE UPPER(name) LIKE UPPER(?)",
628 name)
629 if err != nil {
630 return User{}, err
631 }
632 defer rows.Close()
633 if !rows.Next() {
634 return User{}, errors.New(name + ", user not found")
635 }
636 var u = User{}
637 err = rows.Scan(&u.ID, &u.Name,
638 &u.Description,
639 &u.Registration)
640 if err != nil {
641 return User{}, err
642 }
643 return u, nil
644 }
645
646 func AddUserAccess(owner int, repoID int, user string) error {
647 userID, err := GetUserID(user)
648 if err != nil {
649 return err
650 }
651 if userID == owner {
652 return errors.New(
653 "The repository owner already has maximum privilege")
654 }
655
656 rows, err := db.Query("SELECT privilege FROM access " +
657 "WHERE repoID = ? AND userID = ? ",
658 repoID, userID)
659 if err != nil {
660 return err
661 }
662 defer rows.Close()
663 if rows.Next() {
664 return errors.New("The user already has access")
665 }
666
667 _, err = db.Exec("INSERT INTO access (repoID, userID, privilege) " +
668 "VALUES(?, ?, 1)", repoID, userID)
669 if err != nil {
670 log.Println(err.Error())
671 }
672 return err
673 }
674
675 func AddGroupAccess(repoID int, group string) error {
676 groupID, err := GetGroupID(group)
677 if err != nil {
678 return err
679 }
680
681 rows, err := db.Query("SELECT privilege FROM access " +
682 "WHERE repoID = ? AND groupID = ? ",
683 repoID, groupID)
684 if err != nil {
685 return err
686 }
687 defer rows.Close()
688 if rows.Next() {
689 return errors.New("The group already has access")
690 }
691
692 _, err = db.Exec("INSERT INTO access (repoID, groupID, privilege) " +
693 "VALUES(?, ?, 1)", repoID, groupID)
694 if err != nil {
695 log.Println(err.Error())
696 }
697 return err
698 }
699
700 func RemoveUserAccess(repoID int, userID int) error {
701 statement, err := db.Exec("DELETE FROM access " +
702 "WHERE userID = ? AND repoID = ?",
703 userID, repoID)
704 if err != nil {
705 return err
706 }
707 rows, err := statement.RowsAffected()
708 if err != nil {
709 return err
710 }
711 if rows < 1 {
712 return errors.New("The user is not a contributor")
713 }
714 return nil
715 }
716
717 func RemoveGroupAccess(repoID int, groupID int) error {
718 statement, err := db.Exec("DELETE FROM access " +
719 "WHERE groupID = ? AND repoID = ?",
720 groupID, repoID)
721 if err != nil {
722 return err
723 }
724 rows, err := statement.RowsAffected()
725 if err != nil {
726 return err
727 }
728 if rows < 1 {
729 return errors.New("The group is not a contributor")
730 }
731 return nil
732
733 }
734
735 func GetGroupAccess(repoID int, groupID int) (int, error) {
736 rows, err := db.Query("SELECT privilege FROM access " +
737 "WHERE repoID = ? AND groupID = ? ",
738 repoID, groupID)
739 if err != nil {
740 return -1, err
741 }
742 defer rows.Close()
743 if !rows.Next() {
744 return -1, errors.New("The group is not a contributor")
745 }
746 var privilege int
747 err = rows.Scan(&privilege)
748 if err != nil {
749 return -1, err
750 }
751 return privilege, nil
752 }
753
754 func SetGroupAccess(repoID int, groupID int, privilege int) (error) {
755 _, err := db.Exec("UPDATE access SET privilege = ? " +
756 "WHERE repoID = ? AND groupID = ?",
757 privilege, repoID, groupID)
758 if err != nil {
759 return err
760 }
761 return nil
762 }
763
764 func HasReadAccessTo(userID int) ([]Repo, error) {
765 rows, err := db.Query("SELECT r.repoID, r.userID, r.name, " +
766 "r.creation, r.public, r.description, u.Name " +
767 "FROM access a " +
768 "INNER JOIN member m ON a.groupID = m.groupID " +
769 "INNER JOIN repo r ON a.repoID = r.repoID " +
770 "INNER JOIN user u ON r.userID = u.userID " +
771 "WHERE m.userID = ? AND a.privilege > 0 " +
772 "AND ? <> r.userID " +
773 "UNION " +
774 "SELECT r.repoID, r.userID, r.name, " +
775 "r.creation, r.public, r.description, u.Name " +
776 "FROM access a " +
777 "INNER JOIN repo r ON a.repoID = r.repoID " +
778 "INNER JOIN user u ON r.userID = u.userID " +
779 "WHERE a.userID = ? AND a.privilege > 0 " +
780 "AND ? <> r.userID",
781 userID, userID, userID, userID)
782 if err != nil {
783 return nil, err
784 }
785 defer rows.Close()
786 repos := []Repo{}
787 for rows.Next() {
788 var r Repo
789 err = rows.Scan(&r.RepoID, &r.UserID, &r.Name, &r.Date,
790 &r.IsPublic, &r.Description, &r.Username)
791 if err != nil {
792 return nil, err
793 }
794 repos = append(repos, r)
795 }
796 return repos, nil
797 }
798
799 func GetUserGroupAccess(repoID int, userID int) (int, error) {
800 rows, err := db.Query("SELECT a.privilege FROM access a " +
801 "INNER JOIN member m ON a.groupID = m.groupID " +
802 "WHERE a.repoID = ? AND m.userID = ?",
803 repoID, userID)
804 if err != nil {
805 return -1, err
806 }
807 defer rows.Close()
808 privilege := -1
809 for rows.Next() {
810 var p int
811 err = rows.Scan(&p)
812 if err != nil {
813 return -1, err
814 }
815 if p > privilege {
816 privilege = p
817 }
818 }
819 return privilege, nil
820 }
821
822 func GetUserAccess(repoID int, userID int) (int, error) {
823 rows, err := db.Query("SELECT privilege FROM access " +
824 "WHERE repoID = ? AND userID = ? ",
825 repoID, userID)
826 if err != nil {
827 return -1, err
828 }
829 defer rows.Close()
830 if !rows.Next() {
831 return -1, errors.New("The user is not a contributor")
832 }
833 var privilege int
834 err = rows.Scan(&privilege)
835 if err != nil {
836 return -1, err
837 }
838 return privilege, nil
839 }
840
841 func GetAccess(repoID int, userID int) (int, error) {
842 privilege, err := GetUserGroupAccess(repoID, userID)
843 if err != nil {
844 return -1, err
845 }
846 if privilege == 2 {
847 return 2, nil
848 }
849 p, err := GetUserAccess(repoID, userID)
850 if err != nil {
851 return -1, err
852 }
853 if p < privilege {
854 return privilege, nil
855 }
856 return p, nil
857 }
858
859 func SetUserAccess(repoID int, userID int, privilege int) (error) {
860 _, err := db.Exec("UPDATE access SET privilege = ? " +
861 "WHERE repoID = ? AND userID = ?",
862 privilege, repoID, userID)
863 if err != nil {
864 return err
865 }
866 return nil
867 }
868
869 func GetRepoAccess(repoID int) ([]Access, error) {
870 rows, err := db.Query("SELECT a.repoID, a.userID, b.name, " +
871 "a.privilege FROM access a " +
872 "INNER JOIN user b ON a.userID = b.userID " +
873 "WHERE a.repoID = ?", repoID)
874 if err != nil {
875 log.Println(err.Error())
876 return nil, err
877 }
878 defer rows.Close()
879 var access []Access
880 for rows.Next() {
881 var a = Access{}
882 err = rows.Scan(&a.RepoID, &a.UserID, &a.Name, &a.Privilege)
883 if err != nil {
884 return nil, err
885 }
886 access = append(access, a)
887 }
888 return access, nil
889 }
890
891 func GetRepoGroupAccess(repoID int) ([]Access, error) {
892 rows, err := db.Query("SELECT a.repoID, a.groupID, b.name, " +
893 "a.privilege FROM access a " +
894 "INNER JOIN groups b ON a.groupID = b.groupID " +
895 "WHERE a.repoID = ?", repoID)
896 if err != nil {
897 log.Println(err.Error())
898 return nil, err
899 }
900 defer rows.Close()
901 var access []Access
902 for rows.Next() {
903 var a = Access{}
904 err = rows.Scan(&a.RepoID, &a.UserID, &a.Name, &a.Privilege)
905 if err != nil {
906 return nil, err
907 }
908 access = append(access, a)
909 }
910 return access, nil
911 }
912
913 func (user User) GetRepo(reponame string) (Repo, error) {
914 rows, err := db.Query("SELECT repoID, userID, name, " +
915 "creation, public, description " +
916 "FROM repo WHERE UPPER(name) LIKE UPPER(?) " +
917 "AND userID=?", reponame, user.ID)
918 if err != nil {
919 return Repo{}, err
920 }
921 defer rows.Close()
922 if rows.Next() {
923 var r = Repo{}
924 err = rows.Scan(&r.RepoID, &r.UserID, &r.Name,
925 &r.Date, &r.IsPublic, &r.Description)
926 if err != nil {
927 return Repo{}, err
928 }
929 return r, nil
930 }
931 return Repo{}, errors.New("No repository called " +
932 reponame + " by user " + user.Name)
933 }
934
935 func (user User) GetRepos(onlyPublic bool) ([]Repo, error) {
936 var rows *sql.Rows
937 var err error
938 query := "SELECT repoID, userID, name, " +
939 "creation, public, description " +
940 "FROM repo WHERE userID=?"
941 if onlyPublic {
942 query += " AND public=1"
943 }
944 rows, err = db.Query(query, user.ID)
945 if err != nil {
946 return nil, err
947 }
948 defer rows.Close()
949 var repos []Repo
950 for rows.Next() {
951 var r = Repo{}
952 err = rows.Scan(&r.RepoID, &r.UserID, &r.Name,
953 &r.Date, &r.IsPublic, &r.Description)
954 if err != nil {
955 return nil, err
956 }
957 repos = append(repos, r)
958 }
959 return repos, nil
960 }
961
962 func (user User) GetGroups() ([]Group, error) {
963 var rows *sql.Rows
964 var err error
965 query := "SELECT a.groupID, a.name, a.description FROM groups a " +
966 "INNER JOIN member b ON a.groupID = b.groupID " +
967 "WHERE b.userID = ?"
968 rows, err = db.Query(query, user.ID)
969 if err != nil {
970 return nil, err
971 }
972 defer rows.Close()
973 var groups []Group
974 for rows.Next() {
975 var g = Group{}
976 err = rows.Scan(&g.GroupID, &g.Name, &g.Description)
977 if err != nil {
978 return nil, err
979 }
980 groups = append(groups, g)
981 }
982 return groups, nil
983 }
984
985 func (user User) IsInGroup(group string) (bool, error) {
986 id, err := GetGroupID(group)
987 if err != nil {
988 return false, err
989 }
990 return user.IsInGroupID(id)
991 }
992
993 func (user User) IsInGroupID(groupID int) (bool, error) {
994 query := "SELECT owner FROM member a " +
995 "INNER JOIN groups b ON a.groupID = b.groupID " +
996 "WHERE a.userID = ? AND a.groupID = ? "
997 rows, err := db.Query(query, user.ID, groupID)
998 if err != nil {
999 return false, err
1000 }
1001 defer rows.Close()
1002 if !rows.Next() {
1003 return false, errors.New("Group not found")
1004 }
1005 var owner int
1006 err = rows.Scan(&owner)
1007 if err != nil {
1008 return false, err
1009 }
1010 return owner == user.ID, nil
1011 }
1012
1013 func GetGroupOwner(group string) (Member, error) {
1014 query := "SELECT c.name, a.userID FROM member a " +
1015 "INNER JOIN groups b ON a.groupID = b.groupID " +
1016 "INNER JOIN user c ON a.userID = c.userID " +
1017 "WHERE a.userID = b.owner AND b.name = ? "
1018 rows, err := db.Query(query, group)
1019 if err != nil {
1020 return Member{}, err
1021 }
1022 defer rows.Close()
1023 var m = Member{}
1024 if rows.Next() {
1025 err = rows.Scan(&m.Name, &m.UserID)
1026 if err != nil {
1027 return Member{}, err
1028 }
1029 }
1030 return m, nil
1031 }
1032
1033 func (user User) GetMembers(group string) ([]Member, error) {
1034 var rows *sql.Rows
1035 var err error
1036 query := "SELECT b.Name, b.UserID FROM member a " +
1037 "INNER JOIN user b ON a.userID=b.userID " +
1038 "INNER JOIN groups c ON a.groupID=c.groupID " +
1039 "WHERE c.name = ?"
1040 rows, err = db.Query(query, group)
1041 if err != nil {
1042 return nil, err
1043 }
1044 defer rows.Close()
1045 var members []Member
1046 for rows.Next() {
1047 var m = Member{}
1048 err = rows.Scan(&m.Name, &m.UserID)
1049 if err != nil {
1050 return nil, err
1051 }
1052 members = append(members, m)
1053 }
1054 return members, nil
1055 }
1056
1057 func GetPublicRepo() ([]Repo, error) {
1058 rows, err := db.Query("SELECT b.name, a.repoID, a.userID, a.name, " +
1059 "a.creation, a.public, a.description " +
1060 "FROM repo a INNER JOIN user b " +
1061 "ON a.userID=b.userID WHERE a.public=1")
1062 if err != nil {
1063 return nil, err
1064 }
1065 defer rows.Close()
1066 var repos []Repo
1067 for rows.Next() {
1068 var r = Repo{}
1069 err = rows.Scan(&r.Username, &r.RepoID, &r.UserID, &r.Name,
1070 &r.Date, &r.IsPublic, &r.Description)
1071 if err != nil {
1072 return nil, err
1073 }
1074 repos = append(repos, r)
1075 }
1076 return repos, nil
1077 }
1078
1079 func IsRepoPublic(repo string, username string) (bool, error) {
1080 rows, err := db.Query("SELECT a.public FROM repo a " +
1081 "INNER JOIN user b ON a.userID = b.userID " +
1082 "WHERE UPPER(a.name) LIKE UPPER(?) " +
1083 "AND UPPER(b.name) LIKE UPPER(?)",
1084 repo, username)
1085 if err != nil {
1086 return false, err
1087 }
1088 defer rows.Close()
1089 if rows.Next() {
1090 var public bool
1091 err = rows.Scan(&public)
1092 if err != nil {
1093 return false, err
1094 }
1095 return public, nil
1096 }
1097 return false, errors.New("No repository called " + repo +
1098 " by user " + username)
1099 }
1100
1101 func (user User) TogglePublic(repo string, signature string) error {
1102 if err := user.VerifySignature(signature); err != nil {
1103 return err
1104 }
1105 b, err := IsRepoPublic(repo, user.Name)
1106 if err != nil {
1107 return err
1108 }
1109 i := 1
1110 if b {
1111 i = 0
1112 }
1113 _, err = db.Exec("UPDATE repo SET public=? " +
1114 "WHERE UPPER(name) LIKE UPPER(?) " +
1115 "AND userID=?", i, repo, user.ID)
1116 if err != nil {
1117 return err
1118 }
1119 return nil
1120 }
1121
1122 func (user *User) VerifySignature(signature string) error {
1123 if user.Signature != signature {
1124 return errors.New("wrong signature")
1125 }
1126 if users[signature].ID != user.ID {
1127 return errors.New("signature doesn't match the user")
1128 }
1129 return nil
1130 }
1131
1132 func ChangePassword(username string, password string) error {
1133 err := isPasswordValid(password)
1134 if err != nil {
1135 return err
1136 }
1137 hPassword, err := hashPassword(password)
1138 if err != nil {
1139 return err
1140 }
1141 statement, err := db.Exec("UPDATE user SET password=? " +
1142 "WHERE UPPER(name) LIKE UPPER(?)",
1143 hPassword, username)
1144 if err != nil {
1145 return err
1146 }
1147 rows, err := statement.RowsAffected()
1148 if err != nil {
1149 return err
1150 }
1151 if rows < 1 {
1152 return errors.New("unknown user " + username)
1153 }
1154 return nil
1155 }
1156
1157 func (user User) ChangePassword(password string, signature string) error {
1158 if err := user.VerifySignature(signature); err != nil {
1159 return err
1160 }
1161 return ChangePassword(user.Name, password)
1162 }
1163
1164 func (user User) ChangeDescription(desc string, signature string) error {
1165 if err := user.VerifySignature(signature); err != nil {
1166 return err
1167 }
1168 statement, err := db.Exec("UPDATE user SET description=? " +
1169 "WHERE UPPER(name) LIKE UPPER(?)",
1170 desc, user.Name)
1171 if err != nil {
1172 return err
1173 }
1174 rows, err := statement.RowsAffected()
1175 if err != nil {
1176 return err
1177 }
1178 if rows < 1 {
1179 return errors.New("no description changed")
1180 }
1181 u, b := users[signature]
1182 if !b {
1183 return errors.New("invalid signature detected")
1184 }
1185 u.Description = desc
1186 users[signature] = u
1187 return nil
1188 }
1189
1190 func (user User) Disconnect(signature string) error {
1191 if err := user.VerifySignature(signature); err != nil {
1192 return err
1193 }
1194 delete(users, signature)
1195 _, err := db.Exec("DELETE FROM certificate WHERE hash = ?", signature)
1196 if err != nil {
1197 return err
1198 }
1199 return nil
1200 }
1201
1202 func (user User) ChangeRepoName(name string, newname string,
1203 signature string) error {
1204 if err := user.VerifySignature(signature); err != nil {
1205 return err
1206 }
1207 err := isRepoNameValid(newname)
1208 if err != nil {
1209 return err
1210 }
1211 statement, err := db.Exec("UPDATE repo SET name=? " +
1212 "WHERE UPPER(name) LIKE UPPER(?) " +
1213 "AND userID=?",
1214 newname, name, user.ID)
1215 if err != nil {
1216 return err
1217 }
1218 rows, err := statement.RowsAffected()
1219 if err != nil {
1220 return err
1221 }
1222 if rows < 1 {
1223 return errors.New("failed to change the repository name")
1224 }
1225 return nil
1226 }
1227
1228 func (user User) ChangeRepoDesc(name string, newdesc string) error {
1229 statement, err := db.Exec("UPDATE repo SET description=? " +
1230 "WHERE UPPER(name) LIKE UPPER(?) " +
1231 "AND userID=?", newdesc, name, user.ID)
1232 if err != nil {
1233 return err
1234 }
1235 rows, err := statement.RowsAffected()
1236 if err != nil {
1237 return err
1238 }
1239 if rows > 0 {
1240 return nil
1241 }
1242 return errors.New("failed to change the repository description")
1243 }
1244
1245 func GetRepoDesc(name string, username string) (string, error) {
1246 rows, err := db.Query("SELECT a.description FROM repo a " +
1247 "INNER JOIN user b ON a.userID=b.userID " +
1248 "WHERE UPPER(a.name) LIKE UPPER(?) " +
1249 "AND UPPER(b.name) LIKE UPPER(?)",
1250 name, username)
1251 if err != nil {
1252 return "", err
1253 }
1254 defer rows.Close()
1255 if rows.Next() {
1256 var description string
1257 err = rows.Scan(&description)
1258 if err != nil {
1259 return "", err
1260 }
1261 return description, nil
1262 }
1263 return "", errors.New("No repository called " + name +
1264 " by user " + username)
1265 }
1266
1267 func (user *User) UpdateDescription() error {
1268 rows, err := db.Query("SELECT description FROM user WHERE userID=?",
1269 user.ID)
1270 if err != nil {
1271 return err
1272 }
1273 defer rows.Close()
1274 if rows.Next() {
1275 var dDescription string
1276 err = rows.Scan(&dDescription)
1277 if err != nil {
1278 return err
1279 }
1280 user.Description = dDescription
1281 }
1282 users[user.Signature] = *user
1283 return nil
1284 }
1285