diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7165ba40e..bf77a5dae 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22.5' + go-version: '1.22.11' check-latest: true - name: Build diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d2a8c373..e9838b373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +## [1.47.0] - 2025-30-01 +### Added +- Consolidate the information, and make it accessible with a single API call [#747](https://github.com/rokwire/core-building-block/issues/747) + ## [1.46.0] - 2025-06-01 ### Added - Add filter by ids to public accounts [#744](https://github.com/rokwire/core-building-block/issues/744) diff --git a/SECURITY.md b/SECURITY.md index 0f4073af3..2c252f93f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,8 +4,8 @@ Patches for **Core Building Block** in this repository will only be applied to the following versions: | Version | Supported | | -------- | ------------------ | -|1.46.0 | :white_check_mark: | -| < 1.46.0| :x: | +|1.47.0 | :white_check_mark: | +| < 1.47.0| :x: | ## Reporting a Bug or Vulnerability diff --git a/core/apis.go b/core/apis.go index ba08270b6..c1ae46385 100644 --- a/core/apis.go +++ b/core/apis.go @@ -365,6 +365,10 @@ func (s *servicesImpl) SerGetAppConfig(appTypeIdentifier string, orgID *string, return s.app.serGetAppConfig(appTypeIdentifier, orgID, versionNumbers, apiKey) } +func (s *servicesImpl) GetUserData(appID string, orgID string, accountID string) (*model.UserData, error) { + return s.app.getUserData(appID, orgID, accountID) +} + /// //administrationImpl diff --git a/core/app_services.go b/core/app_services.go index f8c369f98..f8457056d 100644 --- a/core/app_services.go +++ b/core/app_services.go @@ -194,3 +194,18 @@ func (app *application) serGetCommonTest(l *logs.Log) string { func (app *application) serGetAppConfig(appTypeIdentifier string, orgID *string, versionNumbers model.VersionNumbers, apiKey *string) (*model.ApplicationConfig, error) { return app.sharedGetAppConfig(appTypeIdentifier, orgID, versionNumbers, apiKey, false) } + +func (app *application) getUserData(appID string, orgID string, accountID string) (*model.UserData, error) { + account, err := app.storage.FindAccountByID(nil, accountID) + if err != nil { + return nil, err + } + + logginSession, err := app.storage.FindLoginSessionsByParams(appID, orgID, nil, &accountID, nil, nil, nil, nil, nil, nil) + if err != nil { + return nil, err + } + + userData := model.UserData{Account: account, LoginSession: logginSession} + return &userData, nil +} diff --git a/core/interfaces.go b/core/interfaces.go index 0d4c07911..38260ade3 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -48,6 +48,7 @@ type Services interface { SerGetCommonTest(l *logs.Log) string SerGetAppConfig(appTypeIdentifier string, orgID *string, versionNumbers model.VersionNumbers, apiKey *string) (*model.ApplicationConfig, error) + GetUserData(appID string, orgID string, accountID string) (*model.UserData, error) } // Administration exposes administration APIs for the driver adapters diff --git a/core/model/user.go b/core/model/user.go index dc12e78f8..db26e2c4f 100644 --- a/core/model/user.go +++ b/core/model/user.go @@ -215,6 +215,12 @@ type Account struct { LastAccessTokenDate *time.Time } +// UserData represents the current user data +type UserData struct { + Account *Account `json:"account"` + LoginSession []LoginSession `json:"login_sessions"` +} + // HasAppMembership checks if there is app membership func (a Account) HasAppMembership(appOrgID string) bool { if len(a.OrgAppsMemberships) == 0 { diff --git a/driver/web/adapter.go b/driver/web/adapter.go index 07a41798c..f4771221a 100644 --- a/driver/web/adapter.go +++ b/driver/web/adapter.go @@ -142,6 +142,7 @@ func (we Adapter) Start() { servicesSubRouter.HandleFunc("/test", we.wrapFunc(we.servicesApisHandler.getTest, nil)).Methods("GET") //Public servicesSubRouter.HandleFunc("/app-configs", we.wrapFunc(we.servicesApisHandler.getApplicationConfigs, nil)).Methods("POST") //Requires API key in request servicesSubRouter.HandleFunc("/app-configs/organization", we.wrapFunc(we.servicesApisHandler.getApplicationOrgConfigs, we.auth.services.Standard)).Methods("POST") + servicesSubRouter.HandleFunc("/user-data", we.wrapFunc(we.servicesApisHandler.getUserData, we.auth.services.Standard)).Methods("GET") // DEPRECATED servicesSubRouter.HandleFunc("/application/configs", we.wrapFunc(we.servicesApisHandler.getApplicationConfigs, nil)).Methods("POST") //Requires API key in request diff --git a/driver/web/apis_services.go b/driver/web/apis_services.go index 1c5c4238b..f2dd30f8a 100644 --- a/driver/web/apis_services.go +++ b/driver/web/apis_services.go @@ -1301,6 +1301,20 @@ func (h ServicesApisHandler) logout(l *logs.Log, r *http.Request, claims *tokena return l.HTTPResponseSuccess() } +func (h ServicesApisHandler) getUserData(l *logs.Log, r *http.Request, claims *tokenauth.Claims) logs.HTTPResponse { + userData, err := h.coreAPIs.Services.GetUserData(claims.AppID, claims.OrgID, claims.Subject) + if err != nil { + return l.HTTPResponseErrorAction(logutils.ActionGet, model.TypeAccount, nil, err, http.StatusInternalServerError, true) + } + + data, err := json.Marshal(userData) + if err != nil { + return l.HTTPResponseErrorAction(logutils.ActionMarshal, model.TypeAccount, nil, err, http.StatusInternalServerError, false) + } + + return l.HTTPResponseSuccessJSON(data) +} + // NewServicesApisHandler creates new rest services Handler instance func NewServicesApisHandler(coreAPIs *core.APIs) ServicesApisHandler { return ServicesApisHandler{coreAPIs: coreAPIs} diff --git a/driver/web/docs/gen/def.yaml b/driver/web/docs/gen/def.yaml index 999e5b798..2b955fb9b 100644 --- a/driver/web/docs/gen/def.yaml +++ b/driver/web/docs/gen/def.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Rokwire Core Building Block API description: Core Building Block API Documentation - version: 1.46.0 + version: 1.47.0 servers: - url: 'https://api.rokwire.illinois.edu/core' description: Production server @@ -1807,6 +1807,30 @@ paths: description: AppConfig not found '500': description: Internal error + /services/user-data: + get: + tags: + - Services + summary: Get user data + description: | + Gets user data + + **Auth:** Requires auth token + security: + - bearerAuth: [] + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/UserData' + '400': + description: Bad request + '401': + description: Unauthorized + '500': + description: Internal errors /admin/auth/login: post: tags: @@ -7182,6 +7206,15 @@ components: follower_id: readOnly: true type: string + UserData: + type: object + properties: + account: + $ref: '#/components/schemas/Account' + login_sessions: + type: array + items: + $ref: '#/components/schemas/LoginSession' _shared_req_Login: required: - auth_type diff --git a/driver/web/docs/index.yaml b/driver/web/docs/index.yaml index 50924ad6c..1e4068be2 100644 --- a/driver/web/docs/index.yaml +++ b/driver/web/docs/index.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Rokwire Core Building Block API description: Core Building Block API Documentation - version: 1.46.0 + version: 1.47.0 servers: - url: https://api.rokwire.illinois.edu/core description: Production server @@ -95,6 +95,8 @@ paths: $ref: "./resources/services/application/configs.yaml" /services/application/organization/configs: $ref: "./resources/services/application/organization/configs.yaml" + /services/user-data: + $ref: "./resources/services/user-data.yaml" #admin /admin/auth/login: diff --git a/driver/web/docs/resources/services/user-data.yaml b/driver/web/docs/resources/services/user-data.yaml new file mode 100644 index 000000000..e2f0668c6 --- /dev/null +++ b/driver/web/docs/resources/services/user-data.yaml @@ -0,0 +1,23 @@ +get: + tags: + - Services + summary: Get user data + description: | + Gets user data + + **Auth:** Requires auth token + security: + - bearerAuth: [] + responses: + 200: + description: Success + content: + application/json: + schema: + $ref: "../../schemas/user/UserData.yaml" + 400: + description: Bad request + 401: + description: Unauthorized + 500: + description: Internal errors \ No newline at end of file diff --git a/driver/web/docs/schemas/index.yaml b/driver/web/docs/schemas/index.yaml index 7f5b994de..426f90c1f 100644 --- a/driver/web/docs/schemas/index.yaml +++ b/driver/web/docs/schemas/index.yaml @@ -106,6 +106,8 @@ Device: $ref: "./user/Device.yaml" Follow: $ref: "./user/Follow.yaml" +UserData: + $ref: "./user/UserData.yaml" ##### APIs requests and responses - they are at bottom diff --git a/driver/web/docs/schemas/user/UserData.yaml b/driver/web/docs/schemas/user/UserData.yaml new file mode 100644 index 000000000..022a4678c --- /dev/null +++ b/driver/web/docs/schemas/user/UserData.yaml @@ -0,0 +1,8 @@ +type: object +properties: + account: + $ref: "./Account.yaml" + login_sessions: + type: array + items: + $ref: "../auth/LoginSession.yaml" \ No newline at end of file diff --git a/go.mod b/go.mod index 26100c016..8f417553f 100644 --- a/go.mod +++ b/go.mod @@ -16,8 +16,8 @@ require ( github.com/stretchr/testify v1.9.0 github.com/swaggo/http-swagger v1.3.4 go.mongodb.org/mongo-driver v1.15.0 - golang.org/x/crypto v0.23.0 - golang.org/x/sync v0.7.0 + golang.org/x/crypto v0.32.0 + golang.org/x/sync v0.10.0 gopkg.in/go-playground/validator.v9 v9.31.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/yaml.v2 v2.4.0 @@ -71,11 +71,11 @@ require ( github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240424034433-3c2c7870ae76 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect - golang.org/x/tools v0.21.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 2fbd56bc9..71b234087 100644 --- a/go.sum +++ b/go.sum @@ -148,8 +148,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= @@ -162,15 +162,15 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -181,8 +181,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -196,15 +196,15 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=