package db import ( "database/sql" "fmt" "time" "lmvpn/internal/model" ) // CreateProfile inserts a new server profile and returns its ID. func (s *Store) CreateProfile(p *model.ServerProfile) (int64, error) { res, err := s.db.Exec( `INSERT INTO server_profiles (name, server_url, username, auth_mode, routing_mode, custom_cidrs, mtu_override, auto_connect) VALUES (?,?,?,?,?,?,?,?)`, p.Name, p.ServerURL, p.Username, p.AuthMode, p.RoutingMode, p.CustomCIDRs, p.MTUOverride, p.AutoConnect, ) if err != nil { return 0, fmt.Errorf("insert profile: %w", err) } id, _ := res.LastInsertId() p.ID = id p.CreatedAt = time.Now() return id, nil } // GetProfile returns a single profile by ID. func (s *Store) GetProfile(id int64) (*model.ServerProfile, error) { p := &model.ServerProfile{} var last sql.NullTime err := s.db.QueryRow( `SELECT id, name, server_url, username, auth_mode, routing_mode, custom_cidrs, mtu_override, auto_connect, created_at, last_connected_at FROM server_profiles WHERE id = ?`, id, ).Scan(&p.ID, &p.Name, &p.ServerURL, &p.Username, &p.AuthMode, &p.RoutingMode, &p.CustomCIDRs, &p.MTUOverride, &p.AutoConnect, &p.CreatedAt, &last) if err != nil { return nil, fmt.Errorf("get profile %d: %w", id, err) } if last.Valid { p.LastConnectedAt = &last.Time } return p, nil } // ListProfiles returns all saved profiles ordered by name. func (s *Store) ListProfiles() ([]model.ServerProfile, error) { rows, err := s.db.Query( `SELECT id, name, server_url, username, auth_mode, routing_mode, custom_cidrs, mtu_override, auto_connect, created_at, last_connected_at FROM server_profiles ORDER BY name`) if err != nil { return nil, fmt.Errorf("list profiles: %w", err) } defer rows.Close() var out []model.ServerProfile for rows.Next() { var p model.ServerProfile var last sql.NullTime if err := rows.Scan(&p.ID, &p.Name, &p.ServerURL, &p.Username, &p.AuthMode, &p.RoutingMode, &p.CustomCIDRs, &p.MTUOverride, &p.AutoConnect, &p.CreatedAt, &last); err != nil { return nil, err } if last.Valid { p.LastConnectedAt = &last.Time } out = append(out, p) } return out, rows.Err() } // UpdateProfile updates an existing profile. func (s *Store) UpdateProfile(p *model.ServerProfile) error { _, err := s.db.Exec( `UPDATE server_profiles SET name = ?, server_url = ?, username = ?, auth_mode = ?, routing_mode = ?, custom_cidrs = ?, mtu_override = ?, auto_connect = ? WHERE id = ?`, p.Name, p.ServerURL, p.Username, p.AuthMode, p.RoutingMode, p.CustomCIDRs, p.MTUOverride, p.AutoConnect, p.ID) if err != nil { return fmt.Errorf("update profile %d: %w", p.ID, err) } return nil } // DeleteProfile removes a profile by ID. func (s *Store) DeleteProfile(id int64) error { _, err := s.db.Exec(`DELETE FROM server_profiles WHERE id = ?`, id) if err != nil { return fmt.Errorf("delete profile %d: %w", id, err) } return nil } // TouchLastConnected records the connection timestamp for a profile. func (s *Store) TouchLastConnected(id int64) error { _, err := s.db.Exec( `UPDATE server_profiles SET last_connected_at = ? WHERE id = ?`, time.Now(), id) return err }