auth
auth/profile_postgres.go
Fix whitespace in Profile queries. The lack of whitespace around the ` = ?` expression would have bothered me, so I fixed it.
| paddy@148 | 1 package auth |
| paddy@148 | 2 |
| paddy@148 | 3 import ( |
| paddy@148 | 4 "time" |
| paddy@148 | 5 |
| paddy@148 | 6 "code.secondbit.org/uuid.hg" |
| paddy@149 | 7 "github.com/lib/pq" |
| paddy@148 | 8 "github.com/secondbit/pan" |
| paddy@148 | 9 ) |
| paddy@148 | 10 |
| paddy@148 | 11 func (p Profile) GetSQLTableName() string { |
| paddy@148 | 12 return "profiles" |
| paddy@148 | 13 } |
| paddy@148 | 14 |
| paddy@148 | 15 func (l Login) GetSQLTableName() string { |
| paddy@148 | 16 return "logins" |
| paddy@148 | 17 } |
| paddy@148 | 18 |
| paddy@148 | 19 func (p *postgres) getProfileByIDSQL(id uuid.ID) *pan.Query { |
| paddy@148 | 20 var profile Profile |
| paddy@149 | 21 fields, _ := pan.GetFields(profile) |
| paddy@148 | 22 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(profile)) |
| paddy@148 | 23 query.IncludeWhere() |
| paddy@149 | 24 query.Include(pan.GetUnquotedColumn(profile, "ID")+" = ? AND "+pan.GetUnquotedColumn(profile, "Deleted")+" = ?", id, false) |
| paddy@148 | 25 return query.FlushExpressions(" ") |
| paddy@148 | 26 } |
| paddy@148 | 27 |
| paddy@148 | 28 func (p *postgres) getProfileByID(id uuid.ID) (Profile, error) { |
| paddy@148 | 29 query := p.getProfileByIDSQL(id) |
| paddy@148 | 30 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@148 | 31 if err != nil { |
| paddy@148 | 32 return Profile{}, err |
| paddy@148 | 33 } |
| paddy@148 | 34 var profile Profile |
| paddy@149 | 35 var found bool |
| paddy@148 | 36 for rows.Next() { |
| paddy@148 | 37 err := pan.Unmarshal(rows, &profile) |
| paddy@148 | 38 if err != nil { |
| paddy@148 | 39 return Profile{}, err |
| paddy@148 | 40 } |
| paddy@149 | 41 found = true |
| paddy@148 | 42 } |
| paddy@148 | 43 if err := rows.Err(); err != nil { |
| paddy@148 | 44 return Profile{}, err |
| paddy@148 | 45 } |
| paddy@149 | 46 if !found { |
| paddy@149 | 47 return profile, ErrProfileNotFound |
| paddy@149 | 48 } |
| paddy@148 | 49 return profile, nil |
| paddy@148 | 50 } |
| paddy@148 | 51 |
| paddy@148 | 52 func (p *postgres) getProfileByLoginSQL(value string) *pan.Query { |
| paddy@148 | 53 var profile Profile |
| paddy@148 | 54 var login Login |
| paddy@149 | 55 fields, _ := pan.GetUnquotedAbsoluteFields(profile) |
| paddy@148 | 56 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(profile)) |
| paddy@148 | 57 query.Include("INNER JOIN " + pan.GetTableName(login)) |
| paddy@149 | 58 query.Include("ON " + pan.GetUnquotedAbsoluteColumn(profile, "ID") + " = " + pan.GetUnquotedAbsoluteColumn(login, "ProfileID")) |
| paddy@148 | 59 query.IncludeWhere() |
| paddy@149 | 60 query.Include(pan.GetUnquotedAbsoluteColumn(login, "Value")+" = ? AND "+pan.GetUnquotedAbsoluteColumn(profile, "Deleted")+" = ?", value, false) |
| paddy@148 | 61 return query.FlushExpressions(" ") |
| paddy@148 | 62 } |
| paddy@148 | 63 |
| paddy@148 | 64 func (p *postgres) getProfileByLogin(value string) (Profile, error) { |
| paddy@148 | 65 query := p.getProfileByLoginSQL(value) |
| paddy@148 | 66 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@148 | 67 if err != nil { |
| paddy@148 | 68 return Profile{}, err |
| paddy@148 | 69 } |
| paddy@148 | 70 var profile Profile |
| paddy@149 | 71 var found bool |
| paddy@148 | 72 for rows.Next() { |
| paddy@148 | 73 err := pan.Unmarshal(rows, &profile) |
| paddy@148 | 74 if err != nil { |
| paddy@148 | 75 return Profile{}, err |
| paddy@148 | 76 } |
| paddy@149 | 77 found = true |
| paddy@148 | 78 } |
| paddy@148 | 79 if err := rows.Err(); err != nil { |
| paddy@148 | 80 return Profile{}, err |
| paddy@148 | 81 } |
| paddy@149 | 82 if !found { |
| paddy@149 | 83 return profile, ErrProfileNotFound |
| paddy@149 | 84 } |
| paddy@148 | 85 return profile, nil |
| paddy@148 | 86 } |
| paddy@148 | 87 |
| paddy@148 | 88 func (p *postgres) saveProfileSQL(profile Profile) *pan.Query { |
| paddy@149 | 89 fields, values := pan.GetFields(profile) |
| paddy@148 | 90 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(profile)) |
| paddy@148 | 91 query.Include("(" + pan.QueryList(fields) + ")") |
| paddy@148 | 92 query.Include("VALUES") |
| paddy@148 | 93 query.Include("("+pan.VariableList(len(values))+")", values...) |
| paddy@148 | 94 return query.FlushExpressions(" ") |
| paddy@148 | 95 } |
| paddy@148 | 96 |
| paddy@148 | 97 func (p *postgres) saveProfile(profile Profile) error { |
| paddy@148 | 98 query := p.saveProfileSQL(profile) |
| paddy@148 | 99 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@149 | 100 if e, ok := err.(*pq.Error); ok && e.Constraint == "profiles_pkey" { |
| paddy@149 | 101 err = ErrProfileAlreadyExists |
| paddy@149 | 102 } |
| paddy@148 | 103 return err |
| paddy@148 | 104 } |
| paddy@148 | 105 |
| paddy@148 | 106 func (p *postgres) updateProfileSQL(id uuid.ID, change ProfileChange) *pan.Query { |
| paddy@148 | 107 var profile Profile |
| paddy@148 | 108 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(profile)+" SET ") |
| paddy@149 | 109 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Name")+" = ?", change.Name) |
| paddy@149 | 110 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Passphrase")+" = ?", change.Passphrase) |
| paddy@149 | 111 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Iterations")+" = ?", change.Iterations) |
| paddy@149 | 112 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Salt")+" = ?", change.Salt) |
| paddy@149 | 113 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "PassphraseScheme")+" = ?", change.PassphraseScheme) |
| paddy@149 | 114 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Compromised")+" = ?", change.Compromised) |
| paddy@149 | 115 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "LockedUntil")+" = ?", change.LockedUntil) |
| paddy@149 | 116 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "PassphraseReset")+" = ?", change.PassphraseReset) |
| paddy@149 | 117 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "PassphraseResetCreated")+" = ?", change.PassphraseResetCreated) |
| paddy@149 | 118 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "LastSeen")+" = ?", change.LastSeen) |
| paddy@149 | 119 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Deleted")+" = ?", change.Deleted) |
| paddy@148 | 120 query.FlushExpressions(", ") |
| paddy@148 | 121 query.IncludeWhere() |
| paddy@150 | 122 query.Include(pan.GetUnquotedColumn(profile, "ID")+" = ?", id) |
| paddy@148 | 123 return query.FlushExpressions(" ") |
| paddy@148 | 124 } |
| paddy@148 | 125 |
| paddy@148 | 126 func (p *postgres) updateProfile(id uuid.ID, change ProfileChange) error { |
| paddy@149 | 127 if change.Empty() { |
| paddy@149 | 128 return nil |
| paddy@149 | 129 } |
| paddy@148 | 130 query := p.updateProfileSQL(id, change) |
| paddy@148 | 131 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@148 | 132 return err |
| paddy@148 | 133 } |
| paddy@148 | 134 |
| paddy@148 | 135 func (p *postgres) updateProfilesSQL(ids []uuid.ID, change BulkProfileChange) *pan.Query { |
| paddy@149 | 136 if change.Empty() { |
| paddy@149 | 137 return nil |
| paddy@149 | 138 } |
| paddy@148 | 139 var profile Profile |
| paddy@148 | 140 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(profile)+" SET ") |
| paddy@149 | 141 query.IncludeIfNotNil(pan.GetUnquotedColumn(profile, "Compromised")+" = ?", change.Compromised) |
| paddy@148 | 142 query.FlushExpressions(", ") |
| paddy@148 | 143 query.IncludeWhere() |
| paddy@148 | 144 intids := make([]interface{}, len(ids)) |
| paddy@148 | 145 for pos, id := range ids { |
| paddy@148 | 146 intids[pos] = id |
| paddy@148 | 147 } |
| paddy@149 | 148 query.Include(pan.GetUnquotedColumn(profile, "ID")+" IN ("+pan.VariableList(len(ids))+")", intids...) |
| paddy@148 | 149 return query.FlushExpressions(" ") |
| paddy@148 | 150 } |
| paddy@148 | 151 |
| paddy@148 | 152 func (p *postgres) updateProfiles(ids []uuid.ID, change BulkProfileChange) error { |
| paddy@148 | 153 query := p.updateProfilesSQL(ids, change) |
| paddy@148 | 154 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@148 | 155 return err |
| paddy@148 | 156 } |
| paddy@148 | 157 |
| paddy@148 | 158 func (p *postgres) addLoginSQL(login Login) *pan.Query { |
| paddy@149 | 159 fields, values := pan.GetFields(login) |
| paddy@148 | 160 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(login)) |
| paddy@148 | 161 query.Include("(" + pan.QueryList(fields) + ")") |
| paddy@148 | 162 query.Include("VALUES") |
| paddy@148 | 163 query.Include("("+pan.VariableList(len(values))+")", values...) |
| paddy@148 | 164 return query.FlushExpressions(" ") |
| paddy@148 | 165 } |
| paddy@148 | 166 |
| paddy@148 | 167 func (p *postgres) addLogin(login Login) error { |
| paddy@148 | 168 query := p.addLoginSQL(login) |
| paddy@148 | 169 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@149 | 170 if e, ok := err.(*pq.Error); ok && e.Constraint == "logins_pkey" { |
| paddy@149 | 171 return ErrLoginAlreadyExists |
| paddy@149 | 172 } |
| paddy@148 | 173 return err |
| paddy@148 | 174 } |
| paddy@148 | 175 |
| paddy@148 | 176 func (p *postgres) removeLoginSQL(value string, profile uuid.ID) *pan.Query { |
| paddy@148 | 177 var login Login |
| paddy@148 | 178 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(login)) |
| paddy@148 | 179 query.IncludeWhere() |
| paddy@150 | 180 query.Include(pan.GetUnquotedColumn(login, "Value")+" = ? AND "+pan.GetUnquotedColumn(login, "ProfileID")+" = ?", value, profile) |
| paddy@148 | 181 return query.FlushExpressions(" ") |
| paddy@148 | 182 } |
| paddy@148 | 183 |
| paddy@148 | 184 func (p *postgres) removeLogin(value string, profile uuid.ID) error { |
| paddy@148 | 185 query := p.removeLoginSQL(value, profile) |
| paddy@149 | 186 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@149 | 187 if err != nil { |
| paddy@149 | 188 return err |
| paddy@149 | 189 } |
| paddy@149 | 190 rows, err := res.RowsAffected() |
| paddy@149 | 191 if err != nil { |
| paddy@149 | 192 return err |
| paddy@149 | 193 } |
| paddy@149 | 194 if rows == 0 { |
| paddy@149 | 195 return ErrLoginNotFound |
| paddy@149 | 196 } |
| paddy@149 | 197 return nil |
| paddy@148 | 198 } |
| paddy@148 | 199 |
| paddy@148 | 200 func (p *postgres) recordLoginUseSQL(value string, when time.Time) *pan.Query { |
| paddy@148 | 201 var login Login |
| paddy@148 | 202 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(login)+" SET ") |
| paddy@150 | 203 query.Include(pan.GetUnquotedColumn(login, "LastUsed")+" = ?", when) |
| paddy@148 | 204 query.IncludeWhere() |
| paddy@150 | 205 query.Include(pan.GetUnquotedColumn(login, "Value")+" = ?", value) |
| paddy@148 | 206 return query.FlushExpressions(" ") |
| paddy@148 | 207 } |
| paddy@148 | 208 |
| paddy@148 | 209 func (p *postgres) recordLoginUse(value string, when time.Time) error { |
| paddy@148 | 210 query := p.recordLoginUseSQL(value, when) |
| paddy@148 | 211 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@148 | 212 return err |
| paddy@148 | 213 } |
| paddy@148 | 214 |
| paddy@148 | 215 func (p *postgres) listLoginsSQL(profile uuid.ID, num, offset int) *pan.Query { |
| paddy@148 | 216 var login Login |
| paddy@149 | 217 fields, _ := pan.GetFields(login) |
| paddy@148 | 218 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(login)) |
| paddy@148 | 219 query.IncludeWhere() |
| paddy@150 | 220 query.Include(pan.GetUnquotedColumn(login, "ProfileID")+" = ?", profile) |
| paddy@148 | 221 query.IncludeLimit(int64(num)) |
| paddy@148 | 222 query.IncludeOffset(int64(offset)) |
| paddy@148 | 223 return query.FlushExpressions(" ") |
| paddy@148 | 224 } |
| paddy@148 | 225 |
| paddy@148 | 226 func (p *postgres) listLogins(profile uuid.ID, num, offset int) ([]Login, error) { |
| paddy@148 | 227 query := p.listLoginsSQL(profile, num, offset) |
| paddy@148 | 228 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@148 | 229 if err != nil { |
| paddy@148 | 230 return []Login{}, err |
| paddy@148 | 231 } |
| paddy@148 | 232 var logins []Login |
| paddy@148 | 233 for rows.Next() { |
| paddy@148 | 234 var login Login |
| paddy@148 | 235 err = pan.Unmarshal(rows, &login) |
| paddy@148 | 236 if err != nil { |
| paddy@148 | 237 return logins, err |
| paddy@148 | 238 } |
| paddy@148 | 239 logins = append(logins, login) |
| paddy@148 | 240 } |
| paddy@148 | 241 if err := rows.Err(); err != nil { |
| paddy@148 | 242 return logins, err |
| paddy@148 | 243 } |
| paddy@148 | 244 return logins, nil |
| paddy@148 | 245 } |