comparison pkg/auth/opendb.go @ 1341:a0892b578553

Added comments how to use the impersonating database connections from the session middleware.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 26 Nov 2018 10:45:51 +0100
parents cabf4789e02b
children 7cccf7fef3e8
comparison
equal deleted inserted replaced
1340:97430d442909 1341:a0892b578553
25 25
26 "gemma.intevation.de/gemma/pkg/config" 26 "gemma.intevation.de/gemma/pkg/config"
27 ) 27 )
28 28
29 var ( 29 var (
30 // ErrNoMetamorphUser is returned if no metamorphic user is configured.
30 ErrNoMetamorphUser = errors.New("No metamorphic user configured") 31 ErrNoMetamorphUser = errors.New("No metamorphic user configured")
31 ErrNotLoggedIn = errors.New("Not logged in") 32 // ErrNotLoggedIn is returned if there is the user is not logged in.
33 ErrNotLoggedIn = errors.New("Not logged in")
32 ) 34 )
33 35
36 // OpenDB opens up a database connection with a given username and password.
37 // The other credentials are taken from the configuration.
34 func OpenDB(user, password string) (*sql.DB, error) { 38 func OpenDB(user, password string) (*sql.DB, error) {
35 39
36 // To ease SSL config ride a bit on parsing. 40 // To ease SSL config ride a bit on parsing.
37 cc, err := pgx.ParseConnectionString("sslmode=" + config.DBSSLMode()) 41 cc, err := pgx.ParseConnectionString("sslmode=" + config.DBSSLMode())
38 if err != nil { 42 if err != nil {
72 } 76 }
73 m.db = db 77 m.db = db
74 return db, nil 78 return db, nil
75 } 79 }
76 80
77 func MetamorphConn(ctx context.Context, user string) (*sql.Conn, error) { 81 func metamorphConn(ctx context.Context, user string) (*sql.Conn, error) {
78 db, err := mm.open() 82 db, err := mm.open()
79 if err != nil { 83 if err != nil {
80 return nil, err 84 return nil, err
81 } 85 }
82 conn, err := db.Conn(ctx) 86 conn, err := db.Conn(ctx)
100 ) 104 )
101 SELECT rolname FROM pg_roles 105 SELECT rolname FROM pg_roles
102 WHERE oid IN (SELECT oid FROM cte) AND rolname <> current_user 106 WHERE oid IN (SELECT oid FROM cte) AND rolname <> current_user
103 AND EXISTS (SELECT 1 FROM users.list_users WHERE username = current_user)` 107 AND EXISTS (SELECT 1 FROM users.list_users WHERE username = current_user)`
104 108
109 // AllOtherRoles loggs in as user with password and returns a list
110 // of all roles the logged in user has in the system.
105 func AllOtherRoles(user, password string) (Roles, error) { 111 func AllOtherRoles(user, password string) (Roles, error) {
106 db, err := OpenDB(user, password) 112 db, err := OpenDB(user, password)
107 if err != nil { 113 if err != nil {
108 return nil, err 114 return nil, err
109 } 115 }
124 roles = append(roles, role) 130 roles = append(roles, role)
125 } 131 }
126 return roles, rows.Err() 132 return roles, rows.Err()
127 } 133 }
128 134
135 // RunAs runs a given function fn with a database connection impersonated
136 // as the given role.
137 // To make this work a metamorphic user has to be configured in
138 // the system configuration.
129 func RunAs(ctx context.Context, role string, fn func(*sql.Conn) error) error { 139 func RunAs(ctx context.Context, role string, fn func(*sql.Conn) error) error {
130 conn, err := MetamorphConn(ctx, role) 140 conn, err := metamorphConn(ctx, role)
131 if err != nil { 141 if err != nil {
132 return err 142 return err
133 } 143 }
134 defer conn.Close() 144 defer conn.Close()
135 return fn(conn) 145 return fn(conn)
136 } 146 }
137 147
148 // RunAsSessionUser is a convinience wrapper araound which extracts
149 // the logged in user from a session and calls RunAs with it.
138 func RunAsSessionUser(req *http.Request, fn func(*sql.Conn) error) error { 150 func RunAsSessionUser(req *http.Request, fn func(*sql.Conn) error) error {
139 token, ok := GetToken(req) 151 token, ok := GetToken(req)
140 if !ok { 152 if !ok {
141 return ErrNotLoggedIn 153 return ErrNotLoggedIn
142 } 154 }