Add public theme
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 2m52s

This commit is contained in:
Arnaud Delcasse
2026-01-30 18:44:17 +01:00
parent 2333bba79b
commit b5e722ff9b
23 changed files with 249 additions and 112 deletions

1
.gitignore vendored
View File

@@ -3,4 +3,5 @@ themes/*
.vscode .vscode
__debug_bin __debug_bin
parcoursmob parcoursmob
public_themes/
.idea .idea

View File

@@ -30,6 +30,7 @@ FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /themes/ /themes/ COPY --from=builder /themes/ /themes/
COPY --from=builder /public_themes/ /public_themes/
COPY --from=builder /server / COPY --from=builder /server /
EXPOSE 8080 EXPOSE 8080

View File

@@ -27,6 +27,7 @@ func ReadConfig() (*viper.Viper, error) {
"enabled": false, "enabled": false,
"listen": "0.0.0.0:8082", "listen": "0.0.0.0:8082",
"root_dir": "public_themes/default", "root_dir": "public_themes/default",
"contact_email": "contact@example.com",
}, },
}, },
"identification": map[string]any{ "identification": map[string]any{

View File

@@ -77,14 +77,14 @@ func (h *ApplicationHandler) GetAdministrationData(ctx context.Context) (*Admini
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
accounts, accountsErr = h.services.GetAccounts() accounts, accountsErr = h.services.GetAccounts(ctx)
}() }()
// Retrieve beneficiaries in a goroutine // Retrieve beneficiaries in a goroutine
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
beneficiaries, beneficiariesErr = h.services.GetBeneficiaries() beneficiaries, beneficiariesErr = h.services.GetBeneficiaries(ctx)
}() }()
// Retrieve bookings in a goroutine // Retrieve bookings in a goroutine
@@ -570,8 +570,8 @@ func (h *ApplicationHandler) GetBookingsStats(status, startDate, endDate string)
}, nil }, nil
} }
func (h *ApplicationHandler) GetBeneficiariesStats() (*AdminBeneficiariesStatsResult, error) { func (h *ApplicationHandler) GetBeneficiariesStats(ctx context.Context) (*AdminBeneficiariesStatsResult, error) {
beneficiaries, err := h.services.GetBeneficiaries() beneficiaries, err := h.services.GetBeneficiaries(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -179,7 +179,7 @@ func (h *ApplicationHandler) DisplayGroupModule(ctx context.Context, groupID str
h.cache.PutWithTTL(cacheID, accounts, 1*time.Hour) h.cache.PutWithTTL(cacheID, accounts, 1*time.Hour)
// Get beneficiaries in current user's group // Get beneficiaries in current user's group
accountsBeneficiaire, err := h.services.GetBeneficiariesInGroup(currentUserGroup) accountsBeneficiaire, err := h.services.GetBeneficiariesInGroup(ctx, currentUserGroup)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get beneficiaries in group: %w", err) return nil, fmt.Errorf("failed to get beneficiaries in group: %w", err)
} }

View File

@@ -91,7 +91,7 @@ func (h *ApplicationHandler) SearchJourneys(
// SOLIDARITY TRANSPORT // SOLIDARITY TRANSPORT
var err error var err error
drivers, err = h.services.GetAccountsInNamespacesMap([]string{"solidarity_drivers", "organized_carpool_drivers"}) drivers, err = h.services.GetAccountsInNamespacesMap(ctx, []string{"solidarity_drivers", "organized_carpool_drivers"})
if err != nil { if err != nil {
drivers = map[string]mobilityaccountsstorage.Account{} drivers = map[string]mobilityaccountsstorage.Account{}
} }
@@ -99,30 +99,20 @@ func (h *ApplicationHandler) SearchJourneys(
protodep, _ := transformers.GeoJsonToProto(departureGeo) protodep, _ := transformers.GeoJsonToProto(departureGeo)
protodest, _ := transformers.GeoJsonToProto(destinationGeo) protodest, _ := transformers.GeoJsonToProto(destinationGeo)
// Get driver IDs to exclude based on group_id (drivers who already have bookings in this group)
excludedDriverIds := make(map[string]bool)
if solidarityExcludeGroupId != "" {
bookingsResp, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(ctx, &gen.GetSolidarityTransportBookingsRequest{
StartDate: timestamppb.New(time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)),
EndDate: timestamppb.New(time.Date(9999, 12, 31, 0, 0, 0, 0, time.UTC)),
})
if err == nil {
for _, booking := range bookingsResp.Bookings {
if booking.GroupId == solidarityExcludeGroupId {
excludedDriverIds[booking.DriverId] = true
}
}
}
}
if solidarityTransportEnabled { if solidarityTransportEnabled {
log.Debug().Time("departure time", departureDateTime).Msg("calling driver journeys with ...") log.Debug().Time("departure time", departureDateTime).Msg("calling driver journeys with ...")
res, err := h.services.GRPC.SolidarityTransport.GetDriverJourneys(ctx, &gen.GetDriverJourneysRequest{ req := &gen.GetDriverJourneysRequest{
Departure: protodep, Departure: protodep,
Arrival: protodest, Arrival: protodest,
DepartureDate: timestamppb.New(departureDateTime), DepartureDate: timestamppb.New(departureDateTime),
}) }
// Pass exclude_group_id to the service to filter out drivers with bookings in this group
if solidarityExcludeGroupId != "" {
req.ExcludeGroupId = &solidarityExcludeGroupId
}
res, err := h.services.GRPC.SolidarityTransport.GetDriverJourneys(ctx, req)
if err != nil { if err != nil {
log.Error().Err(err).Msg("error in grpc call to GetDriverJourneys") log.Error().Err(err).Msg("error in grpc call to GetDriverJourneys")
} else { } else {
@@ -138,10 +128,6 @@ func (h *ApplicationHandler) SearchJourneys(
if dj.DriverId == solidarityTransportExcludeDriver { if dj.DriverId == solidarityTransportExcludeDriver {
continue continue
} }
// Skip drivers who already have bookings in the same group
if excludedDriverIds[dj.DriverId] {
continue
}
if !yield(dj) { if !yield(dj) {
return return
} }

View File

@@ -21,7 +21,7 @@ type MembersResult struct {
} }
func (h *ApplicationHandler) GetMembers(ctx context.Context) (*MembersResult, error) { func (h *ApplicationHandler) GetMembers(ctx context.Context) (*MembersResult, error) {
accounts, err := h.services.GetAccounts() accounts, err := h.services.GetAccounts(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -212,7 +212,7 @@ func (h *ApplicationHandler) GetOrganizedCarpoolOverview(ctx context.Context, st
} }
} }
beneficiariesMap, err := h.services.GetBeneficiariesMap() beneficiariesMap, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
beneficiariesMap = map[string]mobilityaccountsstorage.Account{} beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
} }
@@ -403,12 +403,12 @@ func (h *ApplicationHandler) GetOrganizedCarpoolBookingData(ctx context.Context,
return nil, fmt.Errorf("carpool booking not found") return nil, fmt.Errorf("carpool booking not found")
} }
driver, err := h.services.GetAccount(resp.Booking.Driver.Id) driver, err := h.services.GetAccount(ctx, resp.Booking.Driver.Id)
if err != nil { if err != nil {
return nil, fmt.Errorf("driver retrieval issue: %w", err) return nil, fmt.Errorf("driver retrieval issue: %w", err)
} }
passenger, err := h.services.GetAccount(resp.Booking.Passenger.Id) passenger, err := h.services.GetAccount(ctx, resp.Booking.Passenger.Id)
if err != nil { if err != nil {
return nil, fmt.Errorf("passenger retrieval issue: %w", err) return nil, fmt.Errorf("passenger retrieval issue: %w", err)
} }
@@ -585,7 +585,7 @@ type OrganizedCarpoolDriverDataResult struct {
func (h *ApplicationHandler) GetOrganizedCarpoolDriverData(ctx context.Context, driverID string) (*OrganizedCarpoolDriverDataResult, error) { func (h *ApplicationHandler) GetOrganizedCarpoolDriverData(ctx context.Context, driverID string) (*OrganizedCarpoolDriverDataResult, error) {
documents := h.filestorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + driverID) documents := h.filestorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + driverID)
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return nil, fmt.Errorf("issue retrieving driver account: %w", err) return nil, fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -686,7 +686,7 @@ type OrganizedCarpoolDriverResult struct {
} }
func (h *ApplicationHandler) GetOrganizedCarpoolDriver(ctx context.Context, driverID string) (*OrganizedCarpoolDriverResult, error) { func (h *ApplicationHandler) GetOrganizedCarpoolDriver(ctx context.Context, driverID string) (*OrganizedCarpoolDriverResult, error) {
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return nil, fmt.Errorf("issue retrieving driver account: %w", err) return nil, fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -703,7 +703,7 @@ func (h *ApplicationHandler) GetOrganizedCarpoolDriver(ctx context.Context, driv
func (h *ApplicationHandler) UpdateOrganizedCarpoolDriver(ctx context.Context, driverID, firstName, lastName, email string, birthdate *time.Time, phoneNumber, fileNumber string, address, addressDestination any, gender, otherProperties string) (string, error) { func (h *ApplicationHandler) UpdateOrganizedCarpoolDriver(ctx context.Context, driverID, firstName, lastName, email string, birthdate *time.Time, phoneNumber, fileNumber string, address, addressDestination any, gender, otherProperties string) (string, error) {
// Security check: verify the account exists and is an organized carpool driver // Security check: verify the account exists and is an organized carpool driver
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return "", fmt.Errorf("issue retrieving driver account: %w", err) return "", fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -786,7 +786,7 @@ func (h *ApplicationHandler) UpdateOrganizedCarpoolDriver(ctx context.Context, d
func (h *ApplicationHandler) ArchiveOrganizedCarpoolDriver(ctx context.Context, driverID string) error { func (h *ApplicationHandler) ArchiveOrganizedCarpoolDriver(ctx context.Context, driverID string) error {
// Security check: verify the account exists and is an organized carpool driver // Security check: verify the account exists and is an organized carpool driver
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return fmt.Errorf("issue retrieving driver account: %w", err) return fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -815,7 +815,7 @@ func (h *ApplicationHandler) ArchiveOrganizedCarpoolDriver(ctx context.Context,
func (h *ApplicationHandler) UnarchiveOrganizedCarpoolDriver(ctx context.Context, driverID string) error { func (h *ApplicationHandler) UnarchiveOrganizedCarpoolDriver(ctx context.Context, driverID string) error {
// Security check: verify the account exists and is an organized carpool driver // Security check: verify the account exists and is an organized carpool driver
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return fmt.Errorf("issue retrieving driver account: %w", err) return fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -844,7 +844,7 @@ func (h *ApplicationHandler) UnarchiveOrganizedCarpoolDriver(ctx context.Context
func (h *ApplicationHandler) AddOrganizedCarpoolDriverDocument(ctx context.Context, driverID string, file io.Reader, filename string, fileSize int64, documentType, documentName string) error { func (h *ApplicationHandler) AddOrganizedCarpoolDriverDocument(ctx context.Context, driverID string, file io.Reader, filename string, fileSize int64, documentType, documentName string) error {
// Security check: verify the account exists and is an organized carpool driver // Security check: verify the account exists and is an organized carpool driver
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return fmt.Errorf("issue retrieving driver account: %w", err) return fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -876,7 +876,7 @@ func (h *ApplicationHandler) DeleteOrganizedCarpoolDriverDocument(ctx context.Co
func (h *ApplicationHandler) AddOrganizedCarpoolTrip(ctx context.Context, driverID, outwardtime, returntime string, departure, destination *geojson.Feature, days map[string]bool) error { func (h *ApplicationHandler) AddOrganizedCarpoolTrip(ctx context.Context, driverID, outwardtime, returntime string, departure, destination *geojson.Feature, days map[string]bool) error {
// Security check: verify the account exists and is an organized carpool driver // Security check: verify the account exists and is an organized carpool driver
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return fmt.Errorf("issue retrieving driver account: %w", err) return fmt.Errorf("issue retrieving driver account: %w", err)
} }
@@ -911,16 +911,20 @@ func (h *ApplicationHandler) AddOrganizedCarpoolTrip(ctx context.Context, driver
for day, enabled := range days { for day, enabled := range days {
if enabled { if enabled {
dayCode := dayMap[day] dayCode := dayMap[day]
if outwardtime != "" {
outwardschedules = append(outwardschedules, map[string]any{ outwardschedules = append(outwardschedules, map[string]any{
"day": dayCode, "day": dayCode,
"time_of_day": outwardtime, "time_of_day": outwardtime,
}) })
}
if returntime != "" {
returnschedules = append(returnschedules, map[string]any{ returnschedules = append(returnschedules, map[string]any{
"day": dayCode, "day": dayCode,
"time_of_day": returntime, "time_of_day": returntime,
}) })
} }
} }
}
outward_fc := geojson.NewFeatureCollection() outward_fc := geojson.NewFeatureCollection()
outward_fc.Append(departure) outward_fc.Append(departure)
@@ -962,12 +966,24 @@ func (h *ApplicationHandler) AddOrganizedCarpoolTrip(ctx context.Context, driver
return fmt.Errorf("failed marshaling return geojson: %w", err) return fmt.Errorf("failed marshaling return geojson: %w", err)
} }
// Only add outward trip if outward time is provided
if outwardtime != "" {
trips = append(trips, &proto.CarpoolFeatureCollection{ trips = append(trips, &proto.CarpoolFeatureCollection{
Serialized: string(outwardtrip), Serialized: string(outwardtrip),
}) })
}
// Only add return trip if return time is provided
if returntime != "" {
trips = append(trips, &proto.CarpoolFeatureCollection{ trips = append(trips, &proto.CarpoolFeatureCollection{
Serialized: string(returntrip), Serialized: string(returntrip),
}) })
}
// If no trips to create, return early
if len(trips) == 0 {
return fmt.Errorf("at least one time (outward or return) must be provided")
}
req := &proto.CreateRegularRoutesRequest{ req := &proto.CreateRegularRoutesRequest{
Routes: trips, Routes: trips,
@@ -1016,21 +1032,21 @@ func (h *ApplicationHandler) GetOrganizedCarpoolJourneyData(ctx context.Context,
return nil, fmt.Errorf("could not unmarshal carpool journey: %w", err) return nil, fmt.Errorf("could not unmarshal carpool journey: %w", err)
} }
driver, err := h.services.GetAccount(driverID) driver, err := h.services.GetAccount(ctx, driverID)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get driver: %w", err) return nil, fmt.Errorf("could not get driver: %w", err)
} }
var passenger mobilityaccountsstorage.Account var passenger mobilityaccountsstorage.Account
if passengerID != "" { if passengerID != "" {
passenger, err = h.services.GetAccount(passengerID) passenger, err = h.services.GetAccount(ctx, passengerID)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get passenger account: %w", err) return nil, fmt.Errorf("could not get passenger account: %w", err)
} }
} }
// Get beneficiaries in current user's group // Get beneficiaries in current user's group
beneficiaries, err := h.services.GetBeneficiariesInGroup(currentUserGroup) beneficiaries, err := h.services.GetBeneficiariesInGroup(ctx, currentUserGroup)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get beneficiaries: %w", err) return nil, fmt.Errorf("could not get beneficiaries: %w", err)
} }
@@ -1192,7 +1208,7 @@ func (h *ApplicationHandler) CreateOrganizedCarpoolJourneyBooking(ctx context.Co
// Get passenger account and calculate pricing // Get passenger account and calculate pricing
var passenger mobilityaccountsstorage.Account var passenger mobilityaccountsstorage.Account
if passengerID != "" { if passengerID != "" {
passenger, err = h.services.GetAccount(passengerID) passenger, err = h.services.GetAccount(ctx, passengerID)
if err != nil { if err != nil {
return "", fmt.Errorf("could not get passenger account: %w", err) return "", fmt.Errorf("could not get passenger account: %w", err)
} }
@@ -1268,7 +1284,7 @@ func (h *ApplicationHandler) CreateOrganizedCarpoolJourneyBooking(ctx context.Co
if message != "" && !doNotSend { if message != "" && !doNotSend {
send_message := strings.ReplaceAll(message, "{booking_id}", bookingRes.Booking.Id) send_message := strings.ReplaceAll(message, "{booking_id}", bookingRes.Booking.Id)
log.Debug().Str("message", send_message).Msg("Carpool booking created: sending message") log.Debug().Str("message", send_message).Msg("Carpool booking created: sending message")
h.GenerateSMS(driverID, send_message) h.GenerateSMS(ctx, driverID, send_message)
} }
return bookingRes.Booking.Id, nil return bookingRes.Booking.Id, nil
@@ -1403,7 +1419,7 @@ func (h *ApplicationHandler) GetOrganizedCarpoolBookings(ctx context.Context, st
} }
// Get beneficiaries // Get beneficiaries
beneficiariesMap, err := h.services.GetBeneficiariesMap() beneficiariesMap, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
beneficiariesMap = map[string]mobilityaccountsstorage.Account{} beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
} }

View File

@@ -8,11 +8,11 @@ import (
) )
func (h *ApplicationHandler) SendSMS(ctx context.Context, beneficiaryID, message string) error { func (h *ApplicationHandler) SendSMS(ctx context.Context, beneficiaryID, message string) error {
return h.GenerateSMS(beneficiaryID, message) return h.GenerateSMS(ctx, beneficiaryID, message)
} }
func (h *ApplicationHandler) GenerateSMS(recipientid string, message string) error { func (h *ApplicationHandler) GenerateSMS(ctx context.Context, recipientid string, message string) error {
recipient, err := h.services.GetAccount(recipientid) recipient, err := h.services.GetAccount(ctx, recipientid)
if err != nil { if err != nil {
log.Error().Err(err).Msg("user not found") log.Error().Err(err).Msg("user not found")
return err return err

View File

@@ -183,7 +183,7 @@ func filterBookingsByGeography(bookings []*solidaritytypes.Booking, departurePol
func (h *ApplicationHandler) GetSolidarityTransportOverview(ctx context.Context, status, driverID, startDate, endDate, departureGeoLayer, departureGeoCode, destinationGeoLayer, destinationGeoCode, passengerAddressGeoLayer, passengerAddressGeoCode, histStatus, histDriverID, histStartDate, histEndDate, histDepartureGeoLayer, histDepartureGeoCode, histDestinationGeoLayer, histDestinationGeoCode, histPassengerAddressGeoLayer, histPassengerAddressGeoCode string, archivedFilter bool, driverAddressGeoLayer, driverAddressGeoCode string) (*SolidarityTransportOverviewResult, error) { func (h *ApplicationHandler) GetSolidarityTransportOverview(ctx context.Context, status, driverID, startDate, endDate, departureGeoLayer, departureGeoCode, destinationGeoLayer, destinationGeoCode, passengerAddressGeoLayer, passengerAddressGeoCode, histStatus, histDriverID, histStartDate, histEndDate, histDepartureGeoLayer, histDepartureGeoCode, histDestinationGeoLayer, histDestinationGeoCode, histPassengerAddressGeoLayer, histPassengerAddressGeoCode string, archivedFilter bool, driverAddressGeoLayer, driverAddressGeoCode string) (*SolidarityTransportOverviewResult, error) {
// Get ALL drivers for the accountsMap (used in bookings display) // Get ALL drivers for the accountsMap (used in bookings display)
allDrivers, err := h.solidarityDrivers("", false) allDrivers, err := h.solidarityDrivers(ctx, "", false)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue getting all solidarity drivers") log.Error().Err(err).Msg("issue getting all solidarity drivers")
allDrivers = []mobilityaccountsstorage.Account{} allDrivers = []mobilityaccountsstorage.Account{}
@@ -196,7 +196,7 @@ func (h *ApplicationHandler) GetSolidarityTransportOverview(ctx context.Context,
} }
// Get filtered drivers for the drivers tab display // Get filtered drivers for the drivers tab display
accounts, err := h.solidarityDrivers("", archivedFilter) accounts, err := h.solidarityDrivers(ctx, "", archivedFilter)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue getting solidarity drivers") log.Error().Err(err).Msg("issue getting solidarity drivers")
accounts = []mobilityaccountsstorage.Account{} accounts = []mobilityaccountsstorage.Account{}
@@ -241,7 +241,7 @@ func (h *ApplicationHandler) GetSolidarityTransportOverview(ctx context.Context,
return strings.Compare(firstNameA, firstNameB) return strings.Compare(firstNameA, firstNameB)
}) })
beneficiariesMap, err := h.services.GetBeneficiariesMap() beneficiariesMap, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
beneficiariesMap = map[string]mobilityaccountsstorage.Account{} beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
} }
@@ -435,7 +435,7 @@ type SolidarityTransportBookingsResult struct {
func (h *ApplicationHandler) GetSolidarityTransportBookings(ctx context.Context, startDate, endDate *time.Time, status, driverID, departureGeoLayer, departureGeoCode, destinationGeoLayer, destinationGeoCode, passengerAddressGeoLayer, passengerAddressGeoCode string) (*SolidarityTransportBookingsResult, error) { func (h *ApplicationHandler) GetSolidarityTransportBookings(ctx context.Context, startDate, endDate *time.Time, status, driverID, departureGeoLayer, departureGeoCode, destinationGeoLayer, destinationGeoCode, passengerAddressGeoLayer, passengerAddressGeoCode string) (*SolidarityTransportBookingsResult, error) {
// Get all drivers // Get all drivers
drivers, err := h.solidarityDrivers("", false) drivers, err := h.solidarityDrivers(ctx, "", false)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue getting solidarity drivers") log.Error().Err(err).Msg("issue getting solidarity drivers")
drivers = []mobilityaccountsstorage.Account{} drivers = []mobilityaccountsstorage.Account{}
@@ -447,7 +447,7 @@ func (h *ApplicationHandler) GetSolidarityTransportBookings(ctx context.Context,
} }
// Get beneficiaries // Get beneficiaries
beneficiariesMap, err := h.services.GetBeneficiariesMap() beneficiariesMap, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
beneficiariesMap = map[string]mobilityaccountsstorage.Account{} beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
} }
@@ -1030,7 +1030,7 @@ func (h *ApplicationHandler) GetSolidarityTransportJourneyData(ctx context.Conte
// Get passenger account // Get passenger account
var passenger mobilityaccountsstorage.Account var passenger mobilityaccountsstorage.Account
if passengerID != "" { if passengerID != "" {
passengerResp, err := h.services.GetAccount(passengerID) passengerResp, err := h.services.GetAccount(ctx, passengerID)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get passenger account: %w", err) return nil, fmt.Errorf("could not get passenger account: %w", err)
} }
@@ -1048,7 +1048,7 @@ func (h *ApplicationHandler) GetSolidarityTransportJourneyData(ctx context.Conte
} }
// Get beneficiaries in current user's group // Get beneficiaries in current user's group
beneficiaries, err := h.services.GetBeneficiariesInGroup(currentUserGroup) beneficiaries, err := h.services.GetBeneficiariesInGroup(ctx, currentUserGroup)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get beneficiaries: %w", err) return nil, fmt.Errorf("could not get beneficiaries: %w", err)
} }
@@ -1093,7 +1093,7 @@ func (h *ApplicationHandler) CreateSolidarityTransportJourneyBooking(ctx context
// Get passenger account for pricing // Get passenger account for pricing
var passenger mobilityaccountsstorage.Account var passenger mobilityaccountsstorage.Account
if passengerID != "" { if passengerID != "" {
passengerResp, err := h.services.GetAccount(passengerID) passengerResp, err := h.services.GetAccount(ctx, passengerID)
if err != nil { if err != nil {
return "", fmt.Errorf("could not get passenger account: %w", err) return "", fmt.Errorf("could not get passenger account: %w", err)
} }
@@ -1171,7 +1171,7 @@ func (h *ApplicationHandler) CreateSolidarityTransportJourneyBooking(ctx context
// Send SMS if not disabled // Send SMS if not disabled
if !doNotSend && message != "" { if !doNotSend && message != "" {
send_message := strings.ReplaceAll(message, "{booking_id}", resp.Booking.Id) send_message := strings.ReplaceAll(message, "{booking_id}", resp.Booking.Id)
if err := h.GenerateSMS(driverID, send_message); err != nil { if err := h.GenerateSMS(ctx, driverID, send_message); err != nil {
log.Error().Err(err).Msg("failed to send SMS") log.Error().Err(err).Msg("failed to send SMS")
} }
} }
@@ -1248,12 +1248,12 @@ func (h *ApplicationHandler) GetSolidarityTransportBookingData(ctx context.Conte
}, nil }, nil
} }
func (h *ApplicationHandler) solidarityDrivers(searchFilter string, archivedFilter bool) ([]mobilityaccountsstorage.Account, error) { func (h *ApplicationHandler) solidarityDrivers(ctx context.Context, searchFilter string, archivedFilter bool) ([]mobilityaccountsstorage.Account, error) {
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{"solidarity_drivers"}, Namespaces: []string{"solidarity_drivers"},
} }
resp, err := h.services.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := h.services.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1320,7 +1320,7 @@ func (h *ApplicationHandler) CalculateSolidarityTransportPricing(ctx context.Con
// Get passenger account // Get passenger account
var passenger mobilityaccountsstorage.Account var passenger mobilityaccountsstorage.Account
if passengerID != "" { if passengerID != "" {
passengerResp, err := h.services.GetAccount(passengerID) passengerResp, err := h.services.GetAccount(ctx, passengerID)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not get passenger account: %w", err) return nil, fmt.Errorf("could not get passenger account: %w", err)
} }
@@ -1376,6 +1376,17 @@ func (h *ApplicationHandler) calculateSolidarityTransportPricing(ctx context.Con
} }
} }
} }
if pst, ok := op_map["previous_solidarity_transport_count"]; ok {
if pst_str, ok := pst.(string); ok {
if pst_str != "" {
if n, err := strconv.Atoi(pst_str); err == nil {
history = history + n
} else {
log.Error().Err(err).Str("n", pst_str).Msg("string to int conversion error")
}
}
}
}
} }
} }
@@ -1459,7 +1470,7 @@ func (h *ApplicationHandler) UpdateSolidarityTransportBookingStatus(ctx context.
if previousStatus != "VALIDATED" && status == "VALIDATED" { if previousStatus != "VALIDATED" && status == "VALIDATED" {
if message != "" { if message != "" {
send_message := strings.ReplaceAll(message, "{booking_id}", bookingID) send_message := strings.ReplaceAll(message, "{booking_id}", bookingID)
h.GenerateSMS(passenger.ID, send_message) h.GenerateSMS(ctx, passenger.ID, send_message)
} }
if err := h.CreditWallet(ctx, passenger.ID, -1*booking.Journey.Price.Amount, "Transport solidaire", "Débit transport solidaire"); err != nil { if err := h.CreditWallet(ctx, passenger.ID, -1*booking.Journey.Price.Amount, "Transport solidaire", "Débit transport solidaire"); err != nil {
return fmt.Errorf("could not debit passenger wallet: %w", err) return fmt.Errorf("could not debit passenger wallet: %w", err)
@@ -1467,6 +1478,32 @@ func (h *ApplicationHandler) UpdateSolidarityTransportBookingStatus(ctx context.
if err := h.CreditWallet(ctx, driver.ID, booking.DriverCompensationAmount, "Transport solidaire", "Crédit transport solidaire"); err != nil { if err := h.CreditWallet(ctx, driver.ID, booking.DriverCompensationAmount, "Transport solidaire", "Crédit transport solidaire"); err != nil {
return fmt.Errorf("could not credit driver wallet: %w", err) return fmt.Errorf("could not credit driver wallet: %w", err)
} }
if notify {
groupsrequest := &groupsmanagement.GetGroupsRequest{
Namespaces: []string{"parcoursmob_organizations"},
Member: booking.PassengerId,
}
groupsresp, err := h.services.GRPC.GroupsManagement.GetGroups(ctx, groupsrequest)
if err != nil {
log.Error().Err(err).Msg("")
} else if len(groupsresp.Groups) > 0 {
members, _, err := h.groupmembers(groupsresp.Groups[0].Id)
if err != nil {
log.Error().Err(err).Msg("could not retrieve groupe members")
} else {
for _, m := range members {
if email, ok := m.Data["email"].(string); ok {
h.emailing.Send("solidarity_transport.booking_driver_accept", email, map[string]string{
"bookingid": booking.Id,
"baseUrl": h.config.GetString("base_url"),
})
}
}
}
}
}
} }
// Credit passenger / debit driver when previous status was VALIDATED and new status is not VALIDATED anymore // Credit passenger / debit driver when previous status was VALIDATED and new status is not VALIDATED anymore

View File

@@ -62,7 +62,7 @@ func (h *ApplicationHandler) GetVehiclesManagementOverview(ctx context.Context,
} }
} }
driversMap, _ := h.services.GetBeneficiariesMap() driversMap, _ := h.services.GetBeneficiariesMap(ctx)
sort.Sort(sorting.VehiclesByLicencePlate(vehicles)) sort.Sort(sorting.VehiclesByLicencePlate(vehicles))
sort.Sort(sorting.BookingsByStartdate(bookings)) sort.Sort(sorting.BookingsByStartdate(bookings))
@@ -180,7 +180,7 @@ func (h *ApplicationHandler) GetVehiclesManagementBookingsList(ctx context.Conte
cacheID := uuid.NewString() cacheID := uuid.NewString()
h.cache.PutWithTTL(cacheID, bookings, 1*time.Hour) h.cache.PutWithTTL(cacheID, bookings, 1*time.Hour)
driversMap, _ := h.services.GetBeneficiariesMap() driversMap, _ := h.services.GetBeneficiariesMap(ctx)
return &VehiclesManagementBookingsListResult{ return &VehiclesManagementBookingsListResult{
VehiclesMap: vehiclesMap, VehiclesMap: vehiclesMap,
@@ -263,7 +263,7 @@ func (h *ApplicationHandler) GetVehicleDisplay(ctx context.Context, vehicleID st
return nil, fmt.Errorf("failed to get vehicle: %w", err) return nil, fmt.Errorf("failed to get vehicle: %w", err)
} }
beneficiaries, err := h.services.GetBeneficiariesMap() beneficiaries, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get beneficiaries: %w", err) return nil, fmt.Errorf("failed to get beneficiaries: %w", err)
} }

View File

@@ -119,7 +119,7 @@ func (h *ApplicationHandler) SearchVehicles(ctx context.Context, beneficiaryID s
beneficiarydocuments = h.filestorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + beneficiary.ID) beneficiarydocuments = h.filestorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + beneficiary.ID)
} }
accounts, err := h.services.GetBeneficiariesMap() accounts, err := h.services.GetBeneficiariesMap(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get beneficiaries: %w", err) return nil, fmt.Errorf("failed to get beneficiaries: %w", err)
} }

View File

@@ -10,7 +10,7 @@ import (
) )
func (h *ApplicationHandler) CreditWallet(ctx context.Context, userid string, amount float64, paymentMethod string, description string) error { func (h *ApplicationHandler) CreditWallet(ctx context.Context, userid string, amount float64, paymentMethod string, description string) error {
account, err := h.services.GetAccount(userid) account, err := h.services.GetAccount(ctx, userid)
if err != nil { if err != nil {
log.Error().Err(err).Msg("could not retrieve account") log.Error().Err(err).Msg("could not retrieve account")
return err return err

3
go.mod
View File

@@ -57,7 +57,7 @@ require (
git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536 git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536
git.coopgo.io/coopgo-platform/saved-search v0.0.0-20251008070953-efccea3f6463 git.coopgo.io/coopgo-platform/saved-search v0.0.0-20251008070953-efccea3f6463
git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af
git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20251016152145-e0882db1bcbc git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20260114093602-8875adbcbbee
github.com/arran4/golang-ical v0.3.1 github.com/arran4/golang-ical v0.3.1
github.com/coreos/go-oidc/v3 v3.11.0 github.com/coreos/go-oidc/v3 v3.11.0
github.com/go-viper/mapstructure/v2 v2.4.0 github.com/go-viper/mapstructure/v2 v2.4.0
@@ -164,6 +164,7 @@ require (
go.etcd.io/etcd/api/v3 v3.5.12 // indirect go.etcd.io/etcd/api/v3 v3.5.12 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
go.mongodb.org/mongo-driver v1.17.4 // indirect go.mongodb.org/mongo-driver v1.17.4 // indirect
go.mongodb.org/mongo-driver/v2 v2.1.0 // indirect
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.21.0 // indirect go.uber.org/zap v1.21.0 // indirect

4
go.sum
View File

@@ -28,6 +28,8 @@ git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af h1:KxHim1dF
git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af/go.mod h1:mad9D+WICDdpJzB+8H/wEVVbllK2mU6VLVByrppc9x0= git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af/go.mod h1:mad9D+WICDdpJzB+8H/wEVVbllK2mU6VLVByrppc9x0=
git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20251016152145-e0882db1bcbc h1:NLU5DUo5Kt3jkPhV3KkqQMahTHIrGildBvYlHwJ6JmM= git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20251016152145-e0882db1bcbc h1:NLU5DUo5Kt3jkPhV3KkqQMahTHIrGildBvYlHwJ6JmM=
git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20251016152145-e0882db1bcbc/go.mod h1:iaFXcIn7DYtKlLrSYs9C47Dt7eeMGYkpx+unLCx8TpQ= git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20251016152145-e0882db1bcbc/go.mod h1:iaFXcIn7DYtKlLrSYs9C47Dt7eeMGYkpx+unLCx8TpQ=
git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20260114093602-8875adbcbbee h1:aoXSugsrZrM8E3WhqOCM+bLgGdxdf7dZAxx/vfbYzWQ=
git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20260114093602-8875adbcbbee/go.mod h1:iaFXcIn7DYtKlLrSYs9C47Dt7eeMGYkpx+unLCx8TpQ=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/DATA-DOG/go-sqlmock v1.3.2/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.3.2/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
@@ -360,6 +362,8 @@ go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg=
go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=

View File

@@ -86,7 +86,7 @@ func main() {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
publicweb.Run(cfg, svc, applicationHandler, kv, filestorage) publicweb.Run(cfg, svc, applicationHandler, kv, filestorage, emailing)
}() }()
} }

View File

@@ -1,6 +1,7 @@
package renderer package renderer
import ( import (
"bytes"
"fmt" "fmt"
"html/template" "html/template"
"net/http" "net/http"
@@ -53,13 +54,22 @@ func (renderer *Renderer) Render(name string, w http.ResponseWriter, r *http.Req
prefixed_files = append(prefixed_files, renderer.templateFile(f)) prefixed_files = append(prefixed_files, renderer.templateFile(f))
} }
w.WriteHeader(http.StatusOK)
t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage)) t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage))
t = template.Must(t.ParseFiles(prefixed_files...)) t = template.Must(t.ParseFiles(prefixed_files...))
err := t.ExecuteTemplate(w, "main", state) // Render to buffer first to avoid write timeouts during template execution
var buf bytes.Buffer
err := t.ExecuteTemplate(&buf, "main", state)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue executing template") log.Error().Err(err).Msg("issue executing template")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
_, err = buf.WriteTo(w)
if err != nil {
log.Error().Err(err).Msg("issue writing template to response")
} }
} }
@@ -69,13 +79,22 @@ func (renderer *Renderer) RenderNoLayout(name string, w http.ResponseWriter, r *
prefixed_files = append(prefixed_files, renderer.templateFile(f)) prefixed_files = append(prefixed_files, renderer.templateFile(f))
} }
w.WriteHeader(http.StatusOK)
t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage)) t := template.New(name).Funcs(GetTemplateFuncMap(state.Group, renderer.GlobalConfig, renderer.FileStorage))
t = template.Must(t.ParseFiles(prefixed_files...)) t = template.Must(t.ParseFiles(prefixed_files...))
err := t.ExecuteTemplate(w, "main", state)
// Render to buffer first to avoid write timeouts during template execution
var buf bytes.Buffer
err := t.ExecuteTemplate(&buf, "main", state)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue executing template") log.Error().Err(err).Msg("issue executing template")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
_, err = buf.WriteTo(w)
if err != nil {
log.Error().Err(err).Msg("issue writing template to response")
} }
} }

64
servers/publicweb/api.go Normal file
View File

@@ -0,0 +1,64 @@
package publicweb
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
)
func (s *PublicWebServer) setupAPIRoutes(r *mux.Router) {
api := r.PathPrefix("/api").Subrouter()
api.HandleFunc("/contact", s.contactHandler).Methods("POST", "OPTIONS")
}
func (s *PublicWebServer) contactHandler(w http.ResponseWriter, r *http.Request) {
// Handle CORS preflight
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
return
}
var data map[string]any
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
log.Error().Err(err).Msg("Failed to decode contact request")
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
if len(data) == 0 {
http.Error(w, "Request body cannot be empty", http.StatusBadRequest)
return
}
// Structure data for email template
emailData := map[string]any{
"baseUrl": s.cfg.GetString("base_url"),
"fields": data,
}
// Send email using the mailer
contactEmail := s.cfg.GetString("server.publicweb.contact_email")
if contactEmail == "" {
log.Error().Msg("Contact email not configured")
http.Error(w, "Contact service not configured", http.StatusInternalServerError)
return
}
if err := s.mailer.Send("contact.request", contactEmail, emailData); err != nil {
log.Error().Err(err).Msg("Failed to send contact email")
http.Error(w, "Failed to send message", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "Message sent successfully",
})
}

View File

@@ -16,6 +16,7 @@ import (
"git.coopgo.io/coopgo-apps/parcoursmob/core/application" "git.coopgo.io/coopgo-apps/parcoursmob/core/application"
cache "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage" cache "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage"
"git.coopgo.io/coopgo-apps/parcoursmob/services" "git.coopgo.io/coopgo-apps/parcoursmob/services"
"git.coopgo.io/coopgo-platform/emailing"
) )
// DataProvider returns data to hydrate a page // DataProvider returns data to hydrate a page
@@ -36,6 +37,7 @@ type PublicWebServer struct {
kv cache.KVHandler kv cache.KVHandler
filestorage cache.FileStorage filestorage cache.FileStorage
applicationHandler *application.ApplicationHandler applicationHandler *application.ApplicationHandler
mailer *emailing.Mailer
rootDir string rootDir string
dynamicRoutes map[string]DynamicRoute dynamicRoutes map[string]DynamicRoute
} }
@@ -46,6 +48,7 @@ func Run(
applicationHandler *application.ApplicationHandler, applicationHandler *application.ApplicationHandler,
kv cache.KVHandler, kv cache.KVHandler,
filestorage cache.FileStorage, filestorage cache.FileStorage,
mailer *emailing.Mailer,
) { ) {
address := cfg.GetString("server.publicweb.listen") address := cfg.GetString("server.publicweb.listen")
rootDir := cfg.GetString("server.publicweb.root_dir") rootDir := cfg.GetString("server.publicweb.root_dir")
@@ -57,6 +60,7 @@ func Run(
kv: kv, kv: kv,
filestorage: filestorage, filestorage: filestorage,
applicationHandler: applicationHandler, applicationHandler: applicationHandler,
mailer: mailer,
rootDir: rootDir, rootDir: rootDir,
dynamicRoutes: make(map[string]DynamicRoute), dynamicRoutes: make(map[string]DynamicRoute),
} }
@@ -67,6 +71,9 @@ func Run(
r.HandleFunc("/health", server.healthHandler).Methods("GET") r.HandleFunc("/health", server.healthHandler).Methods("GET")
// Setup API routes
server.setupAPIRoutes(r)
for pattern := range server.dynamicRoutes { for pattern := range server.dynamicRoutes {
r.HandleFunc(pattern, server.dynamicHandler).Methods("GET", "POST") r.HandleFunc(pattern, server.dynamicHandler).Methods("GET", "POST")
} }

View File

@@ -222,7 +222,7 @@ func (h *Handler) AdminStatsBookingsHTTPHandler() http.HandlerFunc {
func (h *Handler) AdminStatsBeneficiariesHTTPHandler() http.HandlerFunc { func (h *Handler) AdminStatsBeneficiariesHTTPHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
result, err := h.applicationHandler.GetBeneficiariesStats() result, err := h.applicationHandler.GetBeneficiariesStats(r.Context())
if err != nil { if err != nil {
log.Error().Err(err).Msg("error retrieving beneficiaries stats") log.Error().Err(err).Msg("error retrieving beneficiaries stats")
http.Error(w, "Internal Server Error", http.StatusInternalServerError) http.Error(w, "Internal Server Error", http.StatusInternalServerError)

View File

@@ -59,7 +59,7 @@ func (h *Handler) JourneysSearchHTTPHandler() http.HandlerFunc {
var departureGeo *geojson.Feature var departureGeo *geojson.Feature
if departure == "" && passengerID != "" { if departure == "" && passengerID != "" {
// Get passenger address // Get passenger address
p, err := h.services.GetAccount(passengerID) p, err := h.services.GetAccount(r.Context(), passengerID)
if err != nil { if err != nil {
log.Error().Err(err).Msg("could not retrieve passenger") log.Error().Err(err).Msg("could not retrieve passenger")
http.Error(w, "Not Found", http.StatusNotFound) http.Error(w, "Not Found", http.StatusNotFound)
@@ -123,7 +123,7 @@ func (h *Handler) JourneysSearchHTTPHandler() http.HandlerFunc {
} }
group := g.(groupstorage.Group) group := g.(groupstorage.Group)
beneficiaries, err := h.services.GetBeneficiariesInGroup(group) beneficiaries, err := h.services.GetBeneficiariesInGroup(r.Context(), group)
if err != nil { if err != nil {
log.Error().Err(err).Msg("issue retrieving beneficiaries") log.Error().Err(err).Msg("issue retrieving beneficiaries")
http.Error(w, "Internal Server Error", http.StatusInternalServerError) http.Error(w, "Internal Server Error", http.StatusInternalServerError)
@@ -345,7 +345,7 @@ func (h *Handler) JourneysSearchCompactHTTPHandler() http.HandlerFunc {
var departureGeo *geojson.Feature var departureGeo *geojson.Feature
if departure == "" && passengerID != "" { if departure == "" && passengerID != "" {
// Get passenger address // Get passenger address
p, err := h.services.GetAccount(passengerID) p, err := h.services.GetAccount(r.Context(), passengerID)
if err != nil { if err != nil {
log.Error().Err(err).Msg("could not retrieve passenger") log.Error().Err(err).Msg("could not retrieve passenger")
http.Error(w, "Not Found", http.StatusNotFound) http.Error(w, "Not Found", http.StatusNotFound)

View File

@@ -89,8 +89,8 @@ func Run(cfg *viper.Viper, services *services.ServicesHandler, renderer *rendere
srv := &http.Server{ srv := &http.Server{
Handler: r, Handler: r,
Addr: address, Addr: address,
WriteTimeout: 30 * time.Second, WriteTimeout: 120 * time.Second,
ReadTimeout: 15 * time.Second, ReadTimeout: 30 * time.Second,
} }
log.Info().Str("service_name", service_name).Str("address", address).Msg("Running HTTP server") log.Info().Str("service_name", service_name).Str("address", address).Msg("Running HTTP server")

View File

@@ -26,12 +26,12 @@ func NewMobilityAccountService(mobilityAccountsDial string) (*MobilityAccountSer
}, nil }, nil
} }
func (s *ServicesHandler) GetBeneficiaries() (accounts []storage.Account, err error) { func (s *ServicesHandler) GetBeneficiaries(ctx context.Context) (accounts []storage.Account, err error) {
accounts = []storage.Account{} accounts = []storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{"parcoursmob_beneficiaries"}, Namespaces: []string{"parcoursmob_beneficiaries"},
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -43,12 +43,12 @@ func (s *ServicesHandler) GetBeneficiaries() (accounts []storage.Account, err er
return return
} }
func (s *ServicesHandler) GetBeneficiariesMap() (accounts map[string]storage.Account, err error) { func (s *ServicesHandler) GetBeneficiariesMap(ctx context.Context) (accounts map[string]storage.Account, err error) {
accounts = map[string]storage.Account{} accounts = map[string]storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{"parcoursmob_beneficiaries"}, Namespaces: []string{"parcoursmob_beneficiaries"},
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -59,12 +59,12 @@ func (s *ServicesHandler) GetBeneficiariesMap() (accounts map[string]storage.Acc
return return
} }
func (s *ServicesHandler) GetAccounts() (accounts []storage.Account, err error) { func (s *ServicesHandler) GetAccounts(ctx context.Context) (accounts []storage.Account, err error) {
accounts = []storage.Account{} accounts = []storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{"parcoursmob"}, Namespaces: []string{"parcoursmob"},
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -76,12 +76,12 @@ func (s *ServicesHandler) GetAccounts() (accounts []storage.Account, err error)
return return
} }
func (s *ServicesHandler) GetAccountsInNamespace(namespace string) (accounts []storage.Account, err error) { func (s *ServicesHandler) GetAccountsInNamespace(ctx context.Context, namespace string) (accounts []storage.Account, err error) {
accounts = []storage.Account{} accounts = []storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{namespace}, Namespaces: []string{namespace},
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -92,12 +92,12 @@ func (s *ServicesHandler) GetAccountsInNamespace(namespace string) (accounts []s
return return
} }
func (s *ServicesHandler) GetAccountsInNamespaceMap(namespace string) (accounts map[string]storage.Account, err error) { func (s *ServicesHandler) GetAccountsInNamespaceMap(ctx context.Context, namespace string) (accounts map[string]storage.Account, err error) {
accounts = map[string]storage.Account{} accounts = map[string]storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: []string{namespace}, Namespaces: []string{namespace},
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -108,12 +108,12 @@ func (s *ServicesHandler) GetAccountsInNamespaceMap(namespace string) (accounts
return return
} }
func (s *ServicesHandler) GetAccountsInNamespacesMap(namespaces []string) (accounts map[string]storage.Account, err error) { func (s *ServicesHandler) GetAccountsInNamespacesMap(ctx context.Context, namespaces []string) (accounts map[string]storage.Account, err error) {
accounts = map[string]storage.Account{} accounts = map[string]storage.Account{}
request := &mobilityaccounts.GetAccountsRequest{ request := &mobilityaccounts.GetAccountsRequest{
Namespaces: namespaces, Namespaces: namespaces,
} }
resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccounts(ctx, request)
if err == nil { if err == nil {
for _, v := range resp.Accounts { for _, v := range resp.Accounts {
@@ -124,11 +124,11 @@ func (s *ServicesHandler) GetAccountsInNamespacesMap(namespaces []string) (accou
return return
} }
func (s *ServicesHandler) GetAccount(id string) (account storage.Account, err error) { func (s *ServicesHandler) GetAccount(ctx context.Context, id string) (account storage.Account, err error) {
request := &mobilityaccounts.GetAccountRequest{ request := &mobilityaccounts.GetAccountRequest{
Id: id, Id: id,
} }
resp, err := s.GRPC.MobilityAccounts.GetAccount(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccount(ctx, request)
if err != nil { if err != nil {
return storage.Account{}, err return storage.Account{}, err
} }
@@ -136,7 +136,7 @@ func (s *ServicesHandler) GetAccount(id string) (account storage.Account, err er
return resp.Account.ToStorageType(), nil return resp.Account.ToStorageType(), nil
} }
func (s *ServicesHandler) GetBeneficiariesInGroup(group groupstorage.Group) (accounts []storage.Account, err error) { func (s *ServicesHandler) GetBeneficiariesInGroup(ctx context.Context, group groupstorage.Group) (accounts []storage.Account, err error) {
accounts = []storage.Account{} accounts = []storage.Account{}
if len(group.Members) == 0 { if len(group.Members) == 0 {
@@ -147,7 +147,7 @@ func (s *ServicesHandler) GetBeneficiariesInGroup(group groupstorage.Group) (acc
Accountids: group.Members, Accountids: group.Members,
} }
resp, err := s.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), request) resp, err := s.GRPC.MobilityAccounts.GetAccountsBatch(ctx, request)
if err != nil { if err != nil {
return accounts, err return accounts, err
} }