Skip to content

Commit c301edc

Browse files
authored
merge develop into main (#82)
2 parents 4e8df34 + 7e2296f commit c301edc

19 files changed

+319
-5
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
## [1.11.0] - 2024-10-07
9+
### Added
10+
- Consolidate the information, and make it accessible with a single API call [#79](https://github.com/rokwire/surveys-building-block/issues/79)
11+
812
## [1.10.3] - 2024-08-21
913
### Fixed
1014
- Fix GET surveys time filtering [#75](https://github.com/rokwire/surveys-building-block/issues/75)

SECURITY.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Patches for **Surveys Building Block** in this repository will only be applied t
66

77
| Version | Supported |
88
| ------- | ------------------ |
9-
| 1.10.3 | :white_check_mark: |
10-
| < 1.10.3 | :x: |
9+
| 1.11.0 | :white_check_mark: |
10+
| < 1.11.0 | :x: |
1111

1212
## Reporting a Bug or Vulnerability
1313

core/app_client.go

+5
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,11 @@ func (a appClient) CreateSurveyAlert(surveyAlert model.SurveyAlert) error {
182182
return nil
183183
}
184184

185+
// GetUserData returns surveys matching the provided query
186+
func (a appClient) GetUserData(orgID string, appID string, userID *string) (*model.UserData, error) {
187+
return a.app.shared.getUserData(orgID, appID, userID)
188+
}
189+
185190
// newAppClient creates new appClient
186191
func newAppClient(app *Application) appClient {
187192
return appClient{app: app}

core/app_shared.go

+66
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,72 @@ func (a appShared) hasAttendedEvent(orgID string, appID string, eventID string,
152152
return false, nil
153153
}
154154

155+
func (a appShared) getUserData(orgID string, appID string, userID *string) (*model.UserData, error) {
156+
var serveyUserData []model.SurveysUserData
157+
var surveyResponseUserData []model.SurveysResponseUserData
158+
159+
// Create channels for data and error handling
160+
surveysChan := make(chan []model.Survey, 1)
161+
surveysErrChan := make(chan error, 1)
162+
surveyResponsesChan := make(chan []model.SurveyResponse, 1)
163+
surveyResponsesErrChan := make(chan error, 1)
164+
165+
// Fetch surveys asynchronously
166+
go func() {
167+
surveys, err := a.app.storage.GetSurveysLight(orgID, appID, userID)
168+
if err != nil {
169+
surveysErrChan <- err
170+
return
171+
}
172+
surveysChan <- surveys
173+
}()
174+
175+
// Fetch survey responses asynchronously
176+
go func() {
177+
surveysResponses, err := a.app.storage.GetSurveyResponses(&orgID, &appID, userID, nil, nil, nil, nil, nil, nil)
178+
if err != nil {
179+
surveyResponsesErrChan <- err
180+
return
181+
}
182+
surveyResponsesChan <- surveysResponses
183+
}()
184+
185+
// Wait for both operations to complete or return an error
186+
var surveys []model.Survey
187+
var surveysResponses []model.SurveyResponse
188+
189+
for i := 0; i < 2; i++ {
190+
select {
191+
case err := <-surveysErrChan:
192+
return nil, err
193+
case err := <-surveyResponsesErrChan:
194+
return nil, err
195+
case surveys = <-surveysChan:
196+
// Handle the surveys data when received
197+
case surveysResponses = <-surveyResponsesChan:
198+
// Handle the survey responses data when received
199+
}
200+
}
201+
202+
// Process the surveys data
203+
for _, s := range surveys {
204+
survey := model.SurveysUserData{ID: s.ID, CreatorID: s.CreatorID, AppID: s.AppID, AccountID: s.CreatorID,
205+
OrgID: s.OrgID, Title: s.Title, Type: s.Type}
206+
serveyUserData = append(serveyUserData, survey)
207+
}
208+
209+
// Process the survey responses data
210+
for _, sr := range surveysResponses {
211+
surveyResponse := model.SurveysResponseUserData{ID: sr.ID, UserID: sr.UserID, AppID: sr.AppID, AccountID: sr.UserID,
212+
OrgID: sr.OrgID, Title: sr.Survey.Title}
213+
surveyResponseUserData = append(surveyResponseUserData, surveyResponse)
214+
}
215+
216+
// Return the user data after all data has been fetched and processed
217+
userData := model.UserData{SurveyUserData: &serveyUserData, SurveyResponseUserData: &surveyResponseUserData}
218+
return &userData, nil
219+
}
220+
155221
// newAppShared creates new appShared
156222
func newAppShared(app *Application) appShared {
157223
return appShared{app: app}

core/interfaces.go

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ type Shared interface {
2727

2828
isEventAdmin(orgID string, appID string, eventID string, userID string, externalIDs map[string]string) (bool, error)
2929
hasAttendedEvent(orgID string, appID string, eventID string, userID string, externalIDs map[string]string) (bool, error)
30+
31+
getUserData(orgID string, appID string, userID *string) (*model.UserData, error)
3032
}
3133

3234
// Core exposes Core APIs for the driver adapters

core/interfaces/core.go

+3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ type Client interface {
4646

4747
// Survey Alerts
4848
CreateSurveyAlert(surveyAlert model.SurveyAlert) error
49+
50+
// User data
51+
GetUserData(orgID string, appID string, userID *string) (*model.UserData, error)
4952
}
5053

5154
// Admin exposes administrative APIs for the driver adapters

core/interfaces/driven.go

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ type Storage interface {
3434

3535
GetSurvey(id string, orgID string, appID string) (*model.Survey, error)
3636
GetSurveys(orgID string, appID string, creatorID *string, surveyIDs []string, surveyTypes []string, calendarEventID string, limit *int, offset *int, filter *model.SurveyTimeFilter, public *bool, archived *bool, completed *bool) ([]model.Survey, error)
37+
GetSurveysLight(orgID string, appID string, creatorID *string) ([]model.Survey, error)
38+
3739
CreateSurvey(survey model.Survey) (*model.Survey, error)
3840
UpdateSurvey(survey model.Survey, admin bool) error
3941
DeleteSurvey(id string, orgID string, appID string, creatorID string, admin bool) error

core/interfaces/mocks/Storage.go

+31-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/model/surveys.go

+27
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,30 @@ type SurveyTimeFilterRequest struct {
252252
EndTimeAfter *string `json:"end_time_after"`
253253
EndTimeBefore *string `json:"end_time_before"`
254254
}
255+
256+
// SurveysUserData represents user data for surveys
257+
type SurveysUserData struct {
258+
ID string `json:"id" bson:"_id"`
259+
CreatorID string `json:"creator_id" bson:"creator_id"`
260+
AppID string `json:"app_id"`
261+
AccountID string `json:"account_id"`
262+
OrgID string `json:"org_id"`
263+
Title string `json:"title"`
264+
Type string `json:"type"`
265+
}
266+
267+
// SurveysResponseUserData represents user data for surveys responses
268+
type SurveysResponseUserData struct {
269+
ID string `json:"id"`
270+
UserID string `json:"user_id"`
271+
AppID string `json:"app_id"`
272+
AccountID string `json:"account_id"`
273+
OrgID string `json:"org_id"`
274+
Title string `json:"title"`
275+
}
276+
277+
// UserData represents user data
278+
type UserData struct {
279+
SurveyUserData *[]SurveysUserData `json:"survey"`
280+
SurveyResponseUserData *[]SurveysResponseUserData `json:"survey_responses"`
281+
}

driven/storage/adapter_surveys.go

+20
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,26 @@ func (a *Adapter) GetSurveys(orgID string, appID string, creatorID *string, surv
124124
return results, nil
125125
}
126126

127+
// GetSurveysLight gets matching surveys
128+
func (a *Adapter) GetSurveysLight(orgID string, appID string, creatorID *string) ([]model.Survey, error) {
129+
filter := bson.D{
130+
{Key: "org_id", Value: orgID},
131+
{Key: "app_id", Value: appID},
132+
}
133+
134+
if creatorID != nil {
135+
filter = append(filter, bson.E{Key: "creator_id", Value: *creatorID})
136+
}
137+
138+
var results []model.Survey
139+
err := a.db.surveys.Find(a.context, filter, &results, nil)
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
return results, nil
145+
}
146+
127147
// CreateSurvey creates a poll
128148
func (a *Adapter) CreateSurvey(survey model.Survey) (*model.Survey, error) {
129149
_, err := a.db.surveys.InsertOne(a.context, survey)

driver/web/adapter.go

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func (a Adapter) Start() {
8787
mainRouter.HandleFunc("/survey-responses", a.wrapFunc(a.clientAPIsHandler.deleteSurveyResponses, a.auth.client.User)).Methods("DELETE")
8888
mainRouter.HandleFunc("/survey-alerts", a.wrapFunc(a.clientAPIsHandler.createSurveyAlert, a.auth.client.User)).Methods("POST")
8989
mainRouter.HandleFunc("/creator/surveys", a.wrapFunc(a.clientAPIsHandler.getCreatorSurveys, a.auth.client.User)).Methods("GET")
90+
mainRouter.HandleFunc("/user-data", a.wrapFunc(a.clientAPIsHandler.getUserData, a.auth.client.User)).Methods("GET")
9091

9192
// Admin APIs
9293
adminRouter := mainRouter.PathPrefix("/admin").Subrouter()

driver/web/apis_client.go

+14
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,20 @@ func (h ClientAPIsHandler) getCreatorSurveys(l *logs.Log, r *http.Request, claim
587587
return l.HTTPResponseSuccessJSON(data)
588588
}
589589

590+
func (h ClientAPIsHandler) getUserData(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HTTPResponse {
591+
resData, err := h.app.Client.GetUserData(claims.OrgID, claims.AppID, &claims.Subject)
592+
if err != nil {
593+
return l.HTTPResponseErrorAction(logutils.ActionGet, model.TypeSurvey, nil, err, http.StatusInternalServerError, true)
594+
}
595+
596+
data, err := json.Marshal(resData)
597+
if err != nil {
598+
return l.HTTPResponseErrorAction(logutils.ActionMarshal, logutils.TypeResponseBody, nil, err, http.StatusInternalServerError, false)
599+
}
600+
601+
return l.HTTPResponseSuccessJSON(data)
602+
}
603+
590604
// NewClientAPIsHandler creates new client API handler instance
591605
func NewClientAPIsHandler(app *core.Application) ClientAPIsHandler {
592606
return ClientAPIsHandler{app: app}

driver/web/docs/gen/def.yaml

+68-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ openapi: 3.0.3
22
info:
33
title: Rokwire Surveys Building Block API
44
description: Surveys Building Block API Documentation
5-
version: 1.10.3
5+
version: 1.11.0
66
servers:
77
- url: 'https://api.rokwire.illinois.edu/surveys'
88
description: Production server
@@ -712,6 +712,30 @@ paths:
712712
description: Unauthorized
713713
'500':
714714
description: Internal error
715+
/api/user-data:
716+
get:
717+
tags:
718+
- Client
719+
summary: Retrieves surveys
720+
description: |
721+
Retrieves surveys matching the provided query
722+
security:
723+
- bearerAuth: []
724+
responses:
725+
'200':
726+
description: Success
727+
content:
728+
application/json:
729+
schema:
730+
type: array
731+
items:
732+
$ref: '#/components/schemas/UserData'
733+
'400':
734+
description: Bad request
735+
'401':
736+
description: Unauthorized
737+
'500':
738+
description: Internal error
715739
/api/admin/configs:
716740
get:
717741
tags:
@@ -1855,6 +1879,49 @@ components:
18551879
type: string
18561880
params:
18571881
type: object
1882+
UserData:
1883+
type: object
1884+
properties:
1885+
survey:
1886+
type: array
1887+
items:
1888+
type: object
1889+
properties:
1890+
id:
1891+
type: string
1892+
org_id:
1893+
type: string
1894+
app_id:
1895+
type: string
1896+
creator_id:
1897+
type: string
1898+
account_id:
1899+
type: string
1900+
context:
1901+
type: object
1902+
title:
1903+
type: string
1904+
type:
1905+
type: string
1906+
survey_responses:
1907+
type: array
1908+
items:
1909+
type: object
1910+
properties:
1911+
id:
1912+
type: string
1913+
org_id:
1914+
type: string
1915+
app_id:
1916+
type: string
1917+
creator_id:
1918+
type: string
1919+
account_id:
1920+
type: string
1921+
context:
1922+
type: object
1923+
title:
1924+
type: string
18581925
_admin_req_update-configs:
18591926
required:
18601927
- type

driver/web/docs/index.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ openapi: 3.0.3
22
info:
33
title: Rokwire Surveys Building Block API
44
description: Surveys Building Block API Documentation
5-
version: 1.10.3
5+
version: 1.11.0
66
servers:
77
- url: 'https://api.rokwire.illinois.edu/surveys'
88
description: Production server
@@ -45,6 +45,8 @@ paths:
4545
$ref: "./resources/client/survey-alerts.yaml"
4646
/api/creator/surveys:
4747
$ref: "./resources/client/creator/surveys.yaml"
48+
/api/user-data:
49+
$ref: "./resources/client/user-data.yaml"
4850

4951
# Admin
5052
/api/admin/configs:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
get:
2+
tags:
3+
- Client
4+
summary: Retrieves surveys
5+
description: |
6+
Retrieves surveys matching the provided query
7+
security:
8+
- bearerAuth: []
9+
responses:
10+
200:
11+
description: Success
12+
content:
13+
application/json:
14+
schema:
15+
type: array
16+
items:
17+
$ref: "../../schemas/surveys/UserData.yaml"
18+
400:
19+
description: Bad request
20+
401:
21+
description: Unauthorized
22+
500:
23+
description: Internal error

0 commit comments

Comments
 (0)