package application import ( "context" "crypto/rand" "encoding/base64" "fmt" "io" "time" groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" "git.coopgo.io/coopgo-platform/groups-management/storage" accounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "github.com/rs/zerolog/log" ) type GroupSettingsResult struct { Group storage.Group GroupMembers []any Admins []any } func (h *ApplicationHandler) GetGroupSettings(ctx context.Context, groupID string) (*GroupSettingsResult, error) { // Get group info groupResp, err := h.services.GRPC.GroupsManagement.GetGroup(ctx, &groupsmanagement.GetGroupRequest{ Id: groupID, }) if err != nil { return nil, fmt.Errorf("failed to get group: %w", err) } group := groupResp.Group.ToStorageType() members, err := h.members() if err != nil { return nil, fmt.Errorf("failed to get members: %w", err) } admins := []any{} groupMembers := []any{} for _, m := range members { mm := m.ToStorageType() if groups, ok := mm.Data["groups"].([]any); ok { for _, g := range groups { if g.(string) == groupID { groupMembers = append(groupMembers, mm) } if g.(string) == groupID+":admin" { admins = append(admins, mm) } } } } return &GroupSettingsResult{ Group: group, GroupMembers: groupMembers, Admins: admins, }, nil } func (h *ApplicationHandler) InviteMemberToGroup(ctx context.Context, groupID string, username string) error { // Get group info groupResp, err := h.services.GRPC.GroupsManagement.GetGroup(ctx, &groupsmanagement.GetGroupRequest{ Id: groupID, }) if err != nil { return fmt.Errorf("failed to get group: %w", err) } group := groupResp.Group.ToStorageType() accountresp, err := h.services.GRPC.MobilityAccounts.GetAccountUsername(ctx, &accounts.GetAccountUsernameRequest{ Username: username, Namespace: "parcoursmob", }) if err == nil { // Account already exists: adding the existing account to group account := accountresp.Account.ToStorageType() if account.Data["groups"] == nil { account.Data["groups"] = []any{} } account.Data["groups"] = append(account.Data["groups"].([]any), groupID) as, err := accounts.AccountFromStorageType(&account) if err != nil { return fmt.Errorf("failed to convert account: %w", err) } _, err = h.services.GRPC.MobilityAccounts.UpdateData(ctx, &accounts.UpdateDataRequest{ Account: as, }) if err != nil { return fmt.Errorf("failed to update account: %w", err) } data := map[string]any{ "group": group.Data["name"], } if err := h.emailing.Send("onboarding.existing_member", username, data); err != nil { log.Warn().Err(err).Msg("failed to send existing member email") } } else { // Create onboarding for new member onboarding := map[string]any{ "username": username, "group": groupID, "admin": false, } b := make([]byte, 16) if _, err := io.ReadFull(rand.Reader, b); err != nil { return fmt.Errorf("failed to generate random key: %w", err) } key := base64.RawURLEncoding.EncodeToString(b) h.cache.PutWithTTL("onboarding/"+key, onboarding, 72*time.Hour) data := map[string]any{ "group": group.Data["name"], "key": key, } if err := h.emailing.Send("onboarding.new_member", username, data); err != nil { return fmt.Errorf("failed to send new member email: %w", err) } } return nil }