package db import ( "bufio" "database/sql" "fmt" "os" "strings" "syscall" "github.com/go-sql-driver/mysql" "golang.org/x/term" "streifling.com/jason/sicherheitsunterweisung/packages/types" ) type DB struct { *sql.DB Name string } func getUsername() (string, error) { user := os.Getenv("DB_USER") if user == "" { var err error fmt.Printf("DB Benutzer: ") user, err = bufio.NewReader(os.Stdin).ReadString('\n') if err != nil { return "", fmt.Errorf("getUsername: bufio.NewReader(os.Stdin).ReadString('\n'): %v", err) } } return strings.TrimSpace(user), nil } func getPassword() (string, error) { pass := os.Getenv("DB_PASS") if pass == "" { fmt.Printf("DB Passwort: ") bytePass, err := term.ReadPassword(int(syscall.Stdin)) if err != nil { return "", fmt.Errorf("getCredentials: term.ReadPassword(int(syscall.Stdin)): %v", err) } fmt.Println() pass = strings.TrimSpace(string(bytePass)) } return pass, nil } func getCredentials() (string, string, error) { user, err := getUsername() if err != nil { return "", "", fmt.Errorf("getCredentials: getUsername(): %v", err) } pass, err := getPassword() if err != nil { return "", "", fmt.Errorf("getCredentials: getPassword(): %v", err) } return user, pass, nil } func Open(dbName string) (*DB, error) { var err error db := new(DB) cfg := mysql.NewConfig() cfg.DBName = dbName cfg.User, cfg.Passwd, err = getCredentials() if err != nil { return nil, fmt.Errorf("Open: getCredentials(): %v\n", err) } db.Name = dbName db.DB, err = sql.Open("mysql", cfg.FormatDSN()) if err != nil { return nil, fmt.Errorf("Open: sql.Open(\"mysql\", cfg.FormatDSN()): %v\n", err) } if err := db.Ping(); err != nil { return nil, fmt.Errorf("Open: db.Ping(): %v\n", err) } return db, nil } func (db *DB) WriteBriefing(b *types.Briefing) error { result, err := db.Exec(` INSERT INTO briefings (date, time, location, document_name, as_of, instructor_id) VALUES (?, ?, ?, ?, ?, ?) `, b.Date, b.Time, b.Location, b.DocumentName, b.AsOf, b.InstructorID) if err != nil { return fmt.Errorf("*DB.writeBriefing: db.Exec(): %v\n", err) } b.ID, err = result.LastInsertId() if err != nil { return fmt.Errorf("*DB.writeBriefing: result.LastInsertId(): %v\n", err) } return nil } func (db *DB) WriteParticipant(p *types.Participant) error { result, err := db.Exec(` INSERT INTO participants (first_name, last_name, company) VALUES (?, ?, ?) `, p.FirstName, p.LastName, p.Company) if err != nil { return fmt.Errorf("*DB.writeParticipants: db.Exec(): %v\n", err) } p.ID, err = result.LastInsertId() if err != nil { return fmt.Errorf("*DB.writeParticipants: result.LastInsertId(): %v\n", err) } return nil } func (db *DB) WriteGivenAnswer(b *types.Briefing, p *types.Participant, q *types.Question, g *types.GivenAnswer) error { _, err := db.Exec(` INSERT INTO given_answers (briefing_id, participant_id, question_id, given_answer) VALUES (?, ?, ?, ?) `, b.ID, p.ID, q.ID, g) if err != nil { return fmt.Errorf("*DB.writeGivenAnswers: db.Exec(): %v\n", err) } return nil } func (db *DB) WriteAllDataOfBriefing(b *types.Briefing, sp *[]*types.Participant, sq *[]*types.Question, sg *[]*types.GivenAnswer) error { if err := db.WriteBriefing(b); err != nil { return fmt.Errorf("*DB.WriteAllDataOfBriefing: db.writeBriefing(): %v\n", err) } for _, p := range *sp { if err := db.WriteParticipant(p); err != nil { return fmt.Errorf("*DB.WriteAllDataOfBriefing: db.writeParticipants(): %v\n", err) } } for _, p := range *sp { for i, q := range *sq { db.WriteGivenAnswer(b, p, q, (*sg)[i]) } } return nil } func (db *DB) GetAllOverviewTableData() ([]*types.OverviewTableData, error) { rows, err := db.Query(` SELECT i.first_name, i.last_name, b.date, b.time, b.location, b.document_name, b.as_of, p.first_name, p.last_name, p.company FROM given_answers AS g INNER JOIN briefings AS b ON b.id = g.briefing_id INNER JOIN participants AS p ON p.id = g.participant_id INNER JOIN questions AS q ON q.id = g.question_id INNER JOIN instructors AS i ON i.id = b.instructor_id WHERE q.id = 1 ORDER BY b.id DESC, p.id `) if err != nil { return nil, fmt.Errorf("*DB.ReadAllBriefings: db.Query(): %v\n", err) } defer rows.Close() data := make([]*types.OverviewTableData, 0) for rows.Next() { otd := new(types.OverviewTableData) err := rows.Scan( &otd.InstructorFirstName, &otd.InstructorLastName, &otd.BriefingDate, &otd.BriefingTime, &otd.BriefingLocation, &otd.BriefingDocumentName, &otd.BriefingAsOf, &otd.ParticipantFirstName, &otd.ParticipantLastName, &otd.ParticipantCompany, ) if err != nil { return nil, fmt.Errorf("*DB.ReadAllBriefings: rows.Scan(): %v\n", err) } data = append(data, otd) } return data, nil } func (db *DB) GetOverviewTableDataByName(n string) (*[]*types.OverviewTableData, error) { rows, err := db.Query(` SELECT i.first_name, i.last_name, b.date, b.time, b.location, b.document_name, b.as_of, p.first_name, p.last_name, p.company FROM given_answers AS g INNER JOIN briefings AS b ON b.id = g.briefing_id INNER JOIN participants AS p ON p.id = g.participant_id INNER JOIN instructors AS i ON i.id = b.instructor_id WHERE q.id = 1 AND i.first_name LIKE ? OR i.last_name LIKE ? OR p.first_name LIKE ? OR p.last_name LIKE ? ORDER BY b.id DESC, p.id `, "%"+n+"%", "%"+n+"%", "%"+n+"%", "%"+n+"%") if err != nil { return nil, fmt.Errorf("*DB.GetOverviewTableDataByName: db.Query(): %v\n", err) } defer rows.Close() data := make([]*types.OverviewTableData, 0) for rows.Next() { otd := new(types.OverviewTableData) err := rows.Scan( &otd.InstructorFirstName, &otd.InstructorLastName, &otd.BriefingDate, &otd.BriefingTime, &otd.BriefingLocation, &otd.BriefingDocumentName, &otd.BriefingAsOf, &otd.ParticipantFirstName, &otd.ParticipantLastName, &otd.ParticipantCompany, ) if err != nil { return nil, fmt.Errorf("*DB.ReadAllBriefings: rows.Scan(): %v\n", err) } data = append(data, otd) } return &data, nil } func (db *DB) GetLastID(table string) (int, error) { var id int row := db.QueryRow(` SELECT id FROM ? ORDER BY id DESC LIMIT 0, 1 `, table) if err := row.Scan(&id); err != nil { return -1, fmt.Errorf("*DB.GetLastID: row.Scan(): %v\n", err) } return id, nil } func (db *DB) GetInstructors() ([]*types.Instructor, error) { rows, err := db.Query(` SELECT * FROM instructors ORDER BY last_name, first_name `) if err != nil { return nil, fmt.Errorf("*DB.GetInstructors: db.Query(): %v\n", err) } instructors := make([]*types.Instructor, 0) for rows.Next() { instructor := new(types.Instructor) if err = rows.Scan(&instructor.ID, &instructor.FirstName, &instructor.LastName, &instructor.PersonnelID); err != nil { return nil, fmt.Errorf("*DB.GetInstructors: rows.Scan(): %v\n", err) } instructors = append(instructors, instructor) } return instructors, nil }