···107107 -- identifiers108108 id integer primary key autoincrement,109109 pull_id integer not null,110110-110110+111111 -- at identifiers112112 repo_at text not null,113113 owner_did text not null,···194194 created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),195195 foreign key (repo_at) references repos(at_uri) on delete cascade,196196 unique(starred_by_did, repo_at)197197+ );198198+199199+ create table if not exists emails (200200+ id integer primary key autoincrement,201201+ did text not null,202202+ email text not null,203203+ verified integer not null default 0,204204+ verification_code text not null,205205+ is_primary integer not null default 0,206206+ created text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),207207+ unique(did, email)197208 );198209199210 create table if not exists migrations (
+203
appview/db/email.go
···11+package db22+33+import "time"44+55+type Email struct {66+ ID int6477+ Did string88+ Address string99+ Verified bool1010+ Primary bool1111+ VerificationCode string1212+ CreatedAt time.Time1313+}1414+1515+func GetPrimaryEmail(e Execer, did string) (Email, error) {1616+ query := `1717+ select id, did, email, verified, is_primary, verification_code, created1818+ from emails1919+ where did = ? and is_primary = true2020+ `2121+ var email Email2222+ var createdStr string2323+ err := e.QueryRow(query, did).Scan(&email.ID, &email.Did, &email.Address, &email.Verified, &email.Primary, &email.VerificationCode, &createdStr)2424+ if err != nil {2525+ return Email{}, err2626+ }2727+ email.CreatedAt, err = time.Parse(time.RFC3339, createdStr)2828+ if err != nil {2929+ return Email{}, err3030+ }3131+ return email, nil3232+}3333+3434+func GetEmail(e Execer, did string, em string) (Email, error) {3535+ query := `3636+ select id, did, email, verified, is_primary, verification_code, created3737+ from emails3838+ where did = ? and email = ?3939+ `4040+ var email Email4141+ var createdStr string4242+ err := e.QueryRow(query, did, em).Scan(&email.ID, &email.Did, &email.Address, &email.Verified, &email.Primary, &email.VerificationCode, &createdStr)4343+ if err != nil {4444+ return Email{}, err4545+ }4646+ email.CreatedAt, err = time.Parse(time.RFC3339, createdStr)4747+ if err != nil {4848+ return Email{}, err4949+ }5050+ return email, nil5151+}5252+5353+func GetDidForEmail(e Execer, em string) (string, error) {5454+ query := `5555+ select did5656+ from emails5757+ where email = ?5858+ `5959+ var did string6060+ err := e.QueryRow(query, em).Scan(&did)6161+ if err != nil {6262+ return "", err6363+ }6464+ return did, nil6565+}6666+6767+func GetVerificationCodeForEmail(e Execer, did string, email string) (string, error) {6868+ query := `6969+ select verification_code7070+ from emails7171+ where did = ? and email = ?7272+ `7373+ var code string7474+ err := e.QueryRow(query, did, email).Scan(&code)7575+ if err != nil {7676+ return "", err7777+ }7878+ return code, nil7979+}8080+8181+func CheckEmailExists(e Execer, did string, email string) (bool, error) {8282+ query := `8383+ select count(*)8484+ from emails8585+ where did = ? and email = ?8686+ `8787+ var count int8888+ err := e.QueryRow(query, did, email).Scan(&count)8989+ if err != nil {9090+ return false, err9191+ }9292+ return count > 0, nil9393+}9494+9595+func CheckValidVerificationCode(e Execer, did string, email string, code string) (bool, error) {9696+ query := `9797+ select count(*)9898+ from emails9999+ where did = ? and email = ? and verification_code = ?100100+ `101101+ var count int102102+ err := e.QueryRow(query, did, email, code).Scan(&count)103103+ if err != nil {104104+ return false, err105105+ }106106+ return count > 0, nil107107+}108108+109109+func AddEmail(e Execer, email Email) error {110110+ // Check if this is the first email for this DID111111+ countQuery := `112112+ select count(*)113113+ from emails114114+ where did = ?115115+ `116116+ var count int117117+ err := e.QueryRow(countQuery, email.Did).Scan(&count)118118+ if err != nil {119119+ return err120120+ }121121+122122+ // If this is the first email, mark it as primary123123+ if count == 0 {124124+ email.Primary = true125125+ }126126+127127+ query := `128128+ insert into emails (did, email, verified, is_primary, verification_code)129129+ values (?, ?, ?, ?, ?)130130+ `131131+ _, err = e.Exec(query, email.Did, email.Address, email.Verified, email.Primary, email.VerificationCode)132132+ return err133133+}134134+135135+func DeleteEmail(e Execer, did string, email string) error {136136+ query := `137137+ delete from emails138138+ where did = ? and email = ?139139+ `140140+ _, err := e.Exec(query, did, email)141141+ return err142142+}143143+144144+func MarkEmailVerified(e Execer, did string, email string) error {145145+ query := `146146+ update emails147147+ set verified = true148148+ where did = ? and email = ?149149+ `150150+ _, err := e.Exec(query, did, email)151151+ return err152152+}153153+154154+func MakeEmailPrimary(e Execer, did string, email string) error {155155+ // First, unset all primary emails for this DID156156+ query1 := `157157+ update emails158158+ set is_primary = false159159+ where did = ?160160+ `161161+ _, err := e.Exec(query1, did)162162+ if err != nil {163163+ return err164164+ }165165+166166+ // Then, set the specified email as primary167167+ query2 := `168168+ update emails169169+ set is_primary = true170170+ where did = ? and email = ?171171+ `172172+ _, err = e.Exec(query2, did, email)173173+ return err174174+}175175+176176+func GetAllEmails(e Execer, did string) ([]Email, error) {177177+ query := `178178+ select did, email, verified, is_primary, verification_code, created179179+ from emails180180+ where did = ?181181+ `182182+ rows, err := e.Query(query, did)183183+ if err != nil {184184+ return nil, err185185+ }186186+ defer rows.Close()187187+188188+ var emails []Email189189+ for rows.Next() {190190+ var email Email191191+ var createdStr string192192+ err := rows.Scan(&email.Did, &email.Address, &email.Verified, &email.Primary, &email.VerificationCode, &createdStr)193193+ if err != nil {194194+ return nil, err195195+ }196196+ email.CreatedAt, err = time.Parse(time.RFC3339, createdStr)197197+ if err != nil {198198+ return nil, err199199+ }200200+ emails = append(emails, email)201201+ }202202+ return emails, nil203203+}