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