From eb779c2b460fddd7e54ad09f88ae7fddb8dd72c2 Mon Sep 17 00:00:00 2001 From: Maxime Guilbert Date: Thu, 6 Nov 2025 07:02:06 -0500 Subject: [PATCH 1/2] feat: Add admin management endpoints --- CHANGELOG.md | 1 + docs/openapi.yaml | 53 +- pkg/apirouter/routes/v1/admin/admin_router.go | 49 ++ pkg/controllers/admin/add_admin.go | 31 ++ pkg/controllers/admin/get_admins.go | 18 + pkg/controllers/admin/is_admin.go | 4 +- pkg/controllers/admin/remove_admin.go | 31 ++ pkg/dbmodels/admin/admin.go | 8 +- pkg/dbmodels/admin/data_test.go | 6 +- .../admin/mock_admin_management_service.go | 12 +- pkg/models/admin/admin.go | 2 +- .../admin/admin_management_service.go | 18 +- .../admin/admin_management_service_test.go | 34 +- pkg/tools/nosqlstorage/mock/utils.go | 2 +- resources/Iris API.postman_collection.json | 494 +++++++++++++++++- 15 files changed, 718 insertions(+), 45 deletions(-) create mode 100644 pkg/controllers/admin/add_admin.go create mode 100644 pkg/controllers/admin/get_admins.go create mode 100644 pkg/controllers/admin/remove_admin.go diff --git a/CHANGELOG.md b/CHANGELOG.md index c6b6e6b..dbe5fb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Added - docs: Added license +- feat: Add admin management endpoints ### Changed - chore: Update dependencies diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 93f7b4c..3d5dc85 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Iris API description: API to manage ideas, votes, and comments. - version: 1.0.0 + version: 1.1.0 servers: - url: https://api.example.com description: Production server (example) @@ -11,6 +11,52 @@ servers: security: - bearerAuth: [] paths: + /v1/admin: + get: + summary: Get all the admin in database + description: Returns the list of admins + tags: [Admin] + responses: + '200': + description: Admin list + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Admin' + default: + $ref: '#/components/responses/ErrorResponse' + post: + summary: Add an admin + description: Add an user to the admin list + tags: [Admin] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Admin' + responses: + '200': + description: Admin added + default: + $ref: '#/components/responses/ErrorResponse' + delete: + summary: Remove an admin + description: Remove an user to the admin list + tags: [Admin] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Admin' + responses: + '200': + description: Admin removed + default: + $ref: '#/components/responses/ErrorResponse' /v1/admin/me: get: summary: Check if the connected user is an admin @@ -352,6 +398,11 @@ components: schema: $ref: '#/components/schemas/EnhancedError' schemas: + Admin: + type: object + properties: + user_email: + type: string Links: type: object properties: diff --git a/pkg/apirouter/routes/v1/admin/admin_router.go b/pkg/apirouter/routes/v1/admin/admin_router.go index 4310a4f..d37884a 100644 --- a/pkg/apirouter/routes/v1/admin/admin_router.go +++ b/pkg/apirouter/routes/v1/admin/admin_router.go @@ -4,7 +4,11 @@ package admin import ( "fmt" "github.com/RoadTripMoustache/iris_api/pkg/apirouter/middlewares" + apiUtils "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" ctrl "github.com/RoadTripMoustache/iris_api/pkg/controllers/admin" + "github.com/RoadTripMoustache/iris_api/pkg/enum" + "github.com/RoadTripMoustache/iris_api/pkg/errors" + adminsvc "github.com/RoadTripMoustache/iris_api/pkg/services/admin" "github.com/gorilla/mux" "net/http" ) @@ -25,6 +29,51 @@ func New(router *mux.Router, parentPath string) *AdminRouter { // InitRoutes initializes the routes for the admin API. func (p *AdminRouter) InitRoutes() { + // Get the admin list + middlewares.AddRoute( + p.MuxRouter, + http.MethodGet, + p.Path, + http.StatusOK, + func(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + adm, e := adminsvc.GetAdmin(ctx, ctx.UserEmail) + if e != nil || adm == nil { + return nil, errors.New(enum.AuthUnauthorized, nil) + } + + return ctrl.GetAdmins(ctx) + }, + ) + // Add an user as an admin + middlewares.AddRoute( + p.MuxRouter, + http.MethodPost, + p.Path, + http.StatusOK, + func(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + adm, e := adminsvc.GetAdmin(ctx, ctx.UserEmail) + if e != nil || adm == nil { + return nil, errors.New(enum.AuthUnauthorized, nil) + } + + return ctrl.AddAdmin(ctx) + }, + ) + // Remove an user as an admin + middlewares.AddRoute( + p.MuxRouter, + http.MethodDelete, + p.Path, + http.StatusOK, + func(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + adm, e := adminsvc.GetAdmin(ctx, ctx.UserEmail) + if e != nil || adm == nil { + return nil, errors.New(enum.AuthUnauthorized, nil) + } + + return ctrl.RemoveAdmin(ctx) + }, + ) // Check if current user is admin middlewares.AddRoute( p.MuxRouter, diff --git a/pkg/controllers/admin/add_admin.go b/pkg/controllers/admin/add_admin.go new file mode 100644 index 0000000..6409a6f --- /dev/null +++ b/pkg/controllers/admin/add_admin.go @@ -0,0 +1,31 @@ +// Package admin contains all the functions exposed by the Admin controller. +package admin + +import ( + apiUtils "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" + "github.com/RoadTripMoustache/iris_api/pkg/controllers/utils" + "github.com/RoadTripMoustache/iris_api/pkg/dbmodels/admin" + "github.com/RoadTripMoustache/iris_api/pkg/enum" + "github.com/RoadTripMoustache/iris_api/pkg/errors" + adminsvc "github.com/RoadTripMoustache/iris_api/pkg/services/admin" +) + +// AddAdmin - Add an user as admin +func AddAdmin(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + payload := admin.Admin{} + if err := utils.BodyFormatter(ctx.Body, &payload); err != nil { + return nil, errors.New(enum.BadRequest, err) + } + + adm, _ := adminsvc.GetAdmin(ctx, payload.UserEmail) + if adm != nil { + return utils.PrepareResponse(nil) + } + + e := adminsvc.AddAdmin(ctx, payload.UserEmail) + if e != nil { + return nil, e + } + + return utils.PrepareResponse(nil) +} diff --git a/pkg/controllers/admin/get_admins.go b/pkg/controllers/admin/get_admins.go new file mode 100644 index 0000000..95d71dc --- /dev/null +++ b/pkg/controllers/admin/get_admins.go @@ -0,0 +1,18 @@ +// Package admin contains all the functions exposed by the Admin controller. +package admin + +import ( + apiUtils "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" + "github.com/RoadTripMoustache/iris_api/pkg/controllers/utils" + "github.com/RoadTripMoustache/iris_api/pkg/errors" + adminsvc "github.com/RoadTripMoustache/iris_api/pkg/services/admin" +) + +// GetAdmins returns the list of admins +func GetAdmins(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + admList, e := adminsvc.GetAdmins(ctx) + if e != nil { + return nil, e + } + return utils.PrepareResponse(admList) +} diff --git a/pkg/controllers/admin/is_admin.go b/pkg/controllers/admin/is_admin.go index d677762..93fddd5 100644 --- a/pkg/controllers/admin/is_admin.go +++ b/pkg/controllers/admin/is_admin.go @@ -11,10 +11,10 @@ import ( // IsCurrentUserAdmin returns whether the authenticated user is an admin. func IsCurrentUserAdmin(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { - if ctx.UserID == "" { + if ctx.UserEmail == "" { return nil, errors.New(enum.AuthUnauthorized, nil) } - adm, e := adminsvc.GetAdmin(ctx, ctx.UserID) + adm, e := adminsvc.GetAdmin(ctx, ctx.UserEmail) if e != nil { return nil, e } diff --git a/pkg/controllers/admin/remove_admin.go b/pkg/controllers/admin/remove_admin.go new file mode 100644 index 0000000..d104bc3 --- /dev/null +++ b/pkg/controllers/admin/remove_admin.go @@ -0,0 +1,31 @@ +// Package admin contains all the functions exposed by the Admin controller. +package admin + +import ( + apiUtils "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" + "github.com/RoadTripMoustache/iris_api/pkg/controllers/utils" + "github.com/RoadTripMoustache/iris_api/pkg/enum" + "github.com/RoadTripMoustache/iris_api/pkg/errors" + "github.com/RoadTripMoustache/iris_api/pkg/models/admin" + adminsvc "github.com/RoadTripMoustache/iris_api/pkg/services/admin" +) + +// RemoveAdmin - Remove an user from the admin list +func RemoveAdmin(ctx apiUtils.Context) ([]byte, *errors.EnhancedError) { + payload := admin.Admin{} + if err := utils.BodyFormatter(ctx.Body, &payload); err != nil { + return nil, errors.New(enum.BadRequest, err) + } + + adm, _ := adminsvc.GetAdmin(ctx, payload.UserEmail) + if adm == nil { + return utils.PrepareResponse(nil) + } + + e := adminsvc.DeleteAdmin(ctx, payload.UserEmail) + if e != nil { + return nil, e + } + + return utils.PrepareResponse(nil) +} diff --git a/pkg/dbmodels/admin/admin.go b/pkg/dbmodels/admin/admin.go index 059843d..ed4db30 100644 --- a/pkg/dbmodels/admin/admin.go +++ b/pkg/dbmodels/admin/admin.go @@ -8,16 +8,16 @@ import ( const ( AdminCollectionName string = "admins" - AdminUserIDLabel string = "user_id" + AdminUserEmailLabel string = "user_email" ) type Admin struct { - UserID string `json:"user_id"` + UserEmail string `json:"user_email"` } func (a *Admin) ToMap() map[string]interface{} { return map[string]interface{}{ - "user_id": a.UserID, + "user_email": a.UserEmail, } } @@ -31,7 +31,7 @@ func AdminFromMap(m map[string]interface{}) *Admin { func ToAdminModel(admin Admin) models.Admin { modelAdmin := models.Admin{ - UserID: admin.UserID, + UserEmail: admin.UserEmail, } return modelAdmin diff --git a/pkg/dbmodels/admin/data_test.go b/pkg/dbmodels/admin/data_test.go index bbb396e..47b2f76 100644 --- a/pkg/dbmodels/admin/data_test.go +++ b/pkg/dbmodels/admin/data_test.go @@ -6,14 +6,14 @@ import ( var ( adminMap = map[string]interface{}{ - "user_id": "titiU", + "user_email": "titiU", } admin = Admin{ - UserID: "titiU", + UserEmail: "titiU", } adminModel = models.Admin{ - UserID: "titiU", + UserEmail: "titiU", } ) diff --git a/pkg/mocks/services/admin/mock_admin_management_service.go b/pkg/mocks/services/admin/mock_admin_management_service.go index b8eb04d..4091c43 100644 --- a/pkg/mocks/services/admin/mock_admin_management_service.go +++ b/pkg/mocks/services/admin/mock_admin_management_service.go @@ -13,8 +13,8 @@ type MockAdminManagementService struct { mock.Mock } -func (m *MockAdminManagementService) GetAdmin(ctx utils.Context, userID string) (*dbmodels.Admin, *errors.EnhancedError) { - args := m.Called(ctx, userID) +func (m *MockAdminManagementService) GetAdmin(ctx utils.Context, userEmail string) (*dbmodels.Admin, *errors.EnhancedError) { + args := m.Called(ctx, userEmail) var activity *dbmodels.Admin if args.Get(0) != nil { activity = args.Get(0).(*dbmodels.Admin) @@ -39,8 +39,8 @@ func (m *MockAdminManagementService) GetAdmins(ctx utils.Context) ([]*dbmodels.A return admins, enhancedError } -func (m *MockAdminManagementService) AddAdmin(ctx utils.Context, userID string) *errors.EnhancedError { - args := m.Called(ctx, userID) +func (m *MockAdminManagementService) AddAdmin(ctx utils.Context, userEmail string) *errors.EnhancedError { + args := m.Called(ctx, userEmail) var enhancedError *errors.EnhancedError if args.Get(0) != nil { enhancedError = args.Get(0).(*errors.EnhancedError) @@ -48,8 +48,8 @@ func (m *MockAdminManagementService) AddAdmin(ctx utils.Context, userID string) return enhancedError } -func (m *MockAdminManagementService) DeleteAdmin(ctx utils.Context, userID string) *errors.EnhancedError { - args := m.Called(ctx, userID) +func (m *MockAdminManagementService) DeleteAdmin(ctx utils.Context, userEmail string) *errors.EnhancedError { + args := m.Called(ctx, userEmail) var enhancedError *errors.EnhancedError if args.Get(0) != nil { enhancedError = args.Get(0).(*errors.EnhancedError) diff --git a/pkg/models/admin/admin.go b/pkg/models/admin/admin.go index 663053d..4cd3bec 100644 --- a/pkg/models/admin/admin.go +++ b/pkg/models/admin/admin.go @@ -2,5 +2,5 @@ package admin type Admin struct { - UserID string `json:"user_id"` + UserEmail string `json:"user_email"` } diff --git a/pkg/services/admin/admin_management_service.go b/pkg/services/admin/admin_management_service.go index 93e581d..d3acd41 100644 --- a/pkg/services/admin/admin_management_service.go +++ b/pkg/services/admin/admin_management_service.go @@ -18,16 +18,16 @@ var ( // GetAdmin retrieves the admin record for a user with the specified ID. // Parameters: // - ctx: The API context containing request information -// - userID: The ID of the user to check for admin privileges +// - UserEmail: The email of the user to check for admin privileges // // Returns: // - *dbmodels.Admin: The admin record if found, nil otherwise // - *errors.EnhancedError: Error information if the operation fails -func GetAdmin(ctx utils.Context, userID string) (*dbmodels.Admin, *errors.EnhancedError) { +func GetAdmin(ctx utils.Context, userEmail string) (*dbmodels.Admin, *errors.EnhancedError) { requestFilters := []nosqlutils.Filter{{ - Param: dbmodels.AdminUserIDLabel, + Param: dbmodels.AdminUserEmailLabel, Operator: "==", - Value: userID, + Value: userEmail, }} documents := noSQLStorageGetInstance(). @@ -67,12 +67,12 @@ func GetAdmins(ctx utils.Context) ([]*dbmodels.Admin, *errors.EnhancedError) { // If the user already has admin privileges, an error is returned. // Parameters: // - ctx: The API context containing request information -// - userID: The ID of the user to grant admin privileges to +// - userEmail: The email of the user to grant admin privileges to // // Returns: // - *errors.EnhancedError: Error information if the operation fails or if the user already has admin privileges -func AddAdmin(ctx utils.Context, userID string) *errors.EnhancedError { - a, eerr := GetAdmin(ctx, userID) +func AddAdmin(ctx utils.Context, userEmail string) *errors.EnhancedError { + a, eerr := GetAdmin(ctx, userEmail) if eerr != nil { return eerr } @@ -81,7 +81,7 @@ func AddAdmin(ctx utils.Context, userID string) *errors.EnhancedError { } newAdmin := dbmodels.Admin{ - UserID: userID, + UserEmail: userEmail, } err := noSQLStorageGetInstance().Add(dbmodels.AdminCollectionName, newAdmin.ToMap()) @@ -102,7 +102,7 @@ func AddAdmin(ctx utils.Context, userID string) *errors.EnhancedError { // Returns: // - *errors.EnhancedError: Error information if the operation fails func DeleteAdmin(ctx utils.Context, userID string) *errors.EnhancedError { - err := noSQLStorageGetInstance().Delete(dbmodels.AdminCollectionName, userID, dbmodels.AdminUserIDLabel) + err := noSQLStorageGetInstance().Delete(dbmodels.AdminCollectionName, userID, dbmodels.AdminUserEmailLabel) if err != nil { logging.Error(err, nil) return errors.New(enum.InternalServerError, nil) diff --git a/pkg/services/admin/admin_management_service_test.go b/pkg/services/admin/admin_management_service_test.go index 92716c2..22268d4 100644 --- a/pkg/services/admin/admin_management_service_test.go +++ b/pkg/services/admin/admin_management_service_test.go @@ -31,11 +31,11 @@ func Test_GetAdmin(t *testing.T) { queryParams: nil, dbResult: []map[string]interface{}{ { - "user_id": "toto", + "user_email": "toto", }, }, expectedResult: &dbmodels.Admin{ - UserID: "toto", + UserEmail: "toto", }, exprectedErr: nil, }, @@ -44,9 +44,9 @@ func Test_GetAdmin(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.caseDesc, func(t *testing.T) { // --- Given - userID := "toto_uuid" + userEmail := "toto_uuid" ctx := apiUtils.Context{ - UserID: userID, + UserEmail: userEmail, QueryParams: testCase.queryParams, } @@ -54,7 +54,7 @@ func Test_GetAdmin(t *testing.T) { mNoSQLStorageInstance. On("GetFirstDocument", dbmodels.AdminCollectionName, []utils.Filter{{ - Param: dbmodels.AdminUserIDLabel, + Param: dbmodels.AdminUserEmailLabel, Operator: "==", Value: "totoU", }}). @@ -97,12 +97,12 @@ func Test_GetAdmins(t *testing.T) { queryParams: nil, dbResult: []map[string]interface{}{ { - "user_id": "toto", + "user_email": "toto", }, }, expectedResult: []*dbmodels.Admin{ { - UserID: "toto", + UserEmail: "toto", }, }, exprectedErr: nil, @@ -112,18 +112,18 @@ func Test_GetAdmins(t *testing.T) { queryParams: nil, dbResult: []map[string]interface{}{ { - "user_id": "toto", + "user_email": "toto", }, { - "user_id": "titi", + "user_email": "titi", }, }, expectedResult: []*dbmodels.Admin{ { - UserID: "toto", + UserEmail: "toto", }, { - UserID: "titi", + UserEmail: "titi", }, }, exprectedErr: nil, @@ -133,11 +133,11 @@ func Test_GetAdmins(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.caseDesc, func(t *testing.T) { // --- Given - userID := "toto_uuid" + userEmail := "toto_uuid" pageNumber := 1 pageOffset := 0 ctx := apiUtils.Context{ - UserID: userID, + UserEmail: userEmail, QueryParams: testCase.queryParams, Pagination: apiUtils.Pagination{ PageNumber: &pageNumber, @@ -171,10 +171,10 @@ func Test_GetAdmins(t *testing.T) { func Test_AddAdmin(t *testing.T) { // --- Given ctx := apiUtils.Context{ - UserID: "toto", + UserEmail: "toto", } expectedResult := dbmodels.Admin{ - UserID: "titi", + UserEmail: "titi", } mNoSQLStorageInstance := new(services.MockNoSQLStorageInstance) @@ -186,7 +186,7 @@ func Test_AddAdmin(t *testing.T) { mNoSQLStorageInstance. On("GetFirstDocument", dbmodels.AdminCollectionName, []utils.Filter{{ - Param: dbmodels.AdminUserIDLabel, + Param: dbmodels.AdminUserEmailLabel, Operator: "==", Value: "titi", }}). @@ -213,7 +213,7 @@ func Test_DeleteAdmin(t *testing.T) { mNoSQLStorageInstance := new(services.MockNoSQLStorageInstance) var nilError error mNoSQLStorageInstance. - On("Delete", dbmodels.AdminCollectionName, "titi", dbmodels.AdminUserIDLabel). + On("Delete", dbmodels.AdminCollectionName, "titi", dbmodels.AdminUserEmailLabel). Return(nilError) mockNoSQLStorageService := new(services.MockNoSQLStorage) diff --git a/pkg/tools/nosqlstorage/mock/utils.go b/pkg/tools/nosqlstorage/mock/utils.go index 2022986..ea849e4 100644 --- a/pkg/tools/nosqlstorage/mock/utils.go +++ b/pkg/tools/nosqlstorage/mock/utils.go @@ -99,7 +99,7 @@ func (m *MockClient) getDataFromMockFiles(collection string, filters []nosqlUtil func getIDLabel(collection string) string { switch collection { case admin.AdminCollectionName: - return admin.AdminUserIDLabel + return admin.AdminUserEmailLabel } return "uuid" } diff --git a/resources/Iris API.postman_collection.json b/resources/Iris API.postman_collection.json index b69882b..97b733b 100644 --- a/resources/Iris API.postman_collection.json +++ b/resources/Iris API.postman_collection.json @@ -768,7 +768,7 @@ ] }, { - "name": "Récupérer une idée", + "name": "Get Admins", "request": { "auth": { "type": "bearer", @@ -1274,6 +1274,498 @@ } } ] + }, + { + "name": "v1/admin", + "item": [ + { + "name": "Get Admins", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/admin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "admin" + ] + } + }, + "response": [ + { + "name": "Erreur", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error_code\": \"est offic\",\n \"error_message\": \"labore Duis do aute\",\n \"error_http_code\": -5235870,\n \"details\": {}\n}" + }, + { + "name": "Liste des idées", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "[\n {\n \"id\": \"ad\",\n \"created_at\": \"2002-12-07T08:33:52.013Z\",\n \"title\": \"sint aliqua cupidatat\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"Duis velit\",\n \"votes_count\": -3329790,\n \"voters\": [\n \"amet\",\n \"L\"\n ],\n \"comments\": [\n {\n \"id\": \"Excepteur do labore ea\",\n \"created_at\": \"2002-03-17T20:08:27.710Z\",\n \"user_id\": \"id\",\n \"message\": \"enim labore ullamco mollit in\",\n \"images\": [\n \"http://fFplkkPQyjPs.skK,uu+MOD,O2OAUJiYAB8f98akpDuUqB8AFqBxTlhODC-Wu\",\n \"https://iQJQfuqRmRCm.zdwc9UKA9e.1k3pCbNUQIKFIHmOv7zjB\"\n ]\n },\n {\n \"id\": \"ut in qui minim\",\n \"created_at\": \"1985-06-24T16:11:14.687Z\",\n \"user_id\": \"dolore fugiat enim dolor\",\n \"message\": \"dolore cillum irure\",\n \"images\": [\n \"http://qZlkVaUbVSZay.osemOzVda7YXZ8P.NDyv,WR\",\n \"https://VmteLxMHkHmtuycANf.gjknMlPp-uvU0uDPb-FnlU62pLnGyT6EtvoOujKKM1ZIZ4SU\"\n ]\n }\n ],\n \"images\": [\n \"https://fxqsFabaDhtGDdE.pgtrJwqj\",\n \"https://UenRMqEwvZmxqZdkYxhcmuqJ.gxWlFkZxiMe0DR1wQhu\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n },\n {\n \"id\": \"aute nisi in pariatur\",\n \"created_at\": \"1962-12-07T02:49:38.536Z\",\n \"title\": \"incididunt\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"cupidatat officia ullamco\",\n \"votes_count\": -37490083,\n \"voters\": [\n \"cupidatat nulla cillum ad\",\n \"ea exercitation laborum Lorem\"\n ],\n \"comments\": [\n {\n \"id\": \"sit aliquip eu ea\",\n \"created_at\": \"1977-03-26T01:10:13.212Z\",\n \"user_id\": \"fugiat minim laborum\",\n \"message\": \"anim consequat sunt\",\n \"images\": [\n \"https://dTbqflreutw.llusk04c.U8f\",\n \"http://XHEKeSRbVhDNoCHwFYvYF.uhBR22-KXbuezQ,\"\n ]\n },\n {\n \"id\": \"proident reprehenderit sed in\",\n \"created_at\": \"1968-05-20T21:39:40.588Z\",\n \"user_id\": \"incididunt exercitation esse consectetur\",\n \"message\": \"ea officia culpa enim\",\n \"images\": [\n \"http://QIQkmpQYfDMfjSTaUXDTcyxSddzLCK.owsenSB33O5Io\",\n \"https://zcFfqO.vjpkQzd7VQEb9GG+GYuYRF,NaC50NnepKmf57j4NnWspIzTNHZ1LFRmg,CAcMdIpZMDJP-5Z\"\n ]\n }\n ],\n \"images\": [\n \"https://ZdGyKZrvdhyTLSqerYfLn.xvqjJjx0\",\n \"https://YNLgUBLpLfnTbrzMxefhWbdkXVkWh.osmoQDCTO2T3litUw38sB78degoH\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n }\n]" + } + ] + }, + { + "name": "Is admin", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token}}", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/admin/me", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "admin", + "me" + ] + } + }, + "response": [ + { + "name": "Erreur", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error_code\": \"est offic\",\n \"error_message\": \"labore Duis do aute\",\n \"error_http_code\": -5235870,\n \"details\": {}\n}" + }, + { + "name": "Liste des idées", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "[\n {\n \"id\": \"ad\",\n \"created_at\": \"2002-12-07T08:33:52.013Z\",\n \"title\": \"sint aliqua cupidatat\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"Duis velit\",\n \"votes_count\": -3329790,\n \"voters\": [\n \"amet\",\n \"L\"\n ],\n \"comments\": [\n {\n \"id\": \"Excepteur do labore ea\",\n \"created_at\": \"2002-03-17T20:08:27.710Z\",\n \"user_id\": \"id\",\n \"message\": \"enim labore ullamco mollit in\",\n \"images\": [\n \"http://fFplkkPQyjPs.skK,uu+MOD,O2OAUJiYAB8f98akpDuUqB8AFqBxTlhODC-Wu\",\n \"https://iQJQfuqRmRCm.zdwc9UKA9e.1k3pCbNUQIKFIHmOv7zjB\"\n ]\n },\n {\n \"id\": \"ut in qui minim\",\n \"created_at\": \"1985-06-24T16:11:14.687Z\",\n \"user_id\": \"dolore fugiat enim dolor\",\n \"message\": \"dolore cillum irure\",\n \"images\": [\n \"http://qZlkVaUbVSZay.osemOzVda7YXZ8P.NDyv,WR\",\n \"https://VmteLxMHkHmtuycANf.gjknMlPp-uvU0uDPb-FnlU62pLnGyT6EtvoOujKKM1ZIZ4SU\"\n ]\n }\n ],\n \"images\": [\n \"https://fxqsFabaDhtGDdE.pgtrJwqj\",\n \"https://UenRMqEwvZmxqZdkYxhcmuqJ.gxWlFkZxiMe0DR1wQhu\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n },\n {\n \"id\": \"aute nisi in pariatur\",\n \"created_at\": \"1962-12-07T02:49:38.536Z\",\n \"title\": \"incididunt\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"cupidatat officia ullamco\",\n \"votes_count\": -37490083,\n \"voters\": [\n \"cupidatat nulla cillum ad\",\n \"ea exercitation laborum Lorem\"\n ],\n \"comments\": [\n {\n \"id\": \"sit aliquip eu ea\",\n \"created_at\": \"1977-03-26T01:10:13.212Z\",\n \"user_id\": \"fugiat minim laborum\",\n \"message\": \"anim consequat sunt\",\n \"images\": [\n \"https://dTbqflreutw.llusk04c.U8f\",\n \"http://XHEKeSRbVhDNoCHwFYvYF.uhBR22-KXbuezQ,\"\n ]\n },\n {\n \"id\": \"proident reprehenderit sed in\",\n \"created_at\": \"1968-05-20T21:39:40.588Z\",\n \"user_id\": \"incididunt exercitation esse consectetur\",\n \"message\": \"ea officia culpa enim\",\n \"images\": [\n \"http://QIQkmpQYfDMfjSTaUXDTcyxSddzLCK.owsenSB33O5Io\",\n \"https://zcFfqO.vjpkQzd7VQEb9GG+GYuYRF,NaC50NnepKmf57j4NnWspIzTNHZ1LFRmg,CAcMdIpZMDJP-5Z\"\n ]\n }\n ],\n \"images\": [\n \"https://ZdGyKZrvdhyTLSqerYfLn.xvqjJjx0\",\n \"https://YNLgUBLpLfnTbrzMxefhWbdkXVkWh.osmoQDCTO2T3litUw38sB78degoH\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n }\n]" + } + ] + }, + { + "name": "Add admin", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token}}", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"user_email\": \"pouet@bncx.de\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/admin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "admin" + ] + } + }, + "response": [ + { + "name": "Erreur", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error_code\": \"est offic\",\n \"error_message\": \"labore Duis do aute\",\n \"error_http_code\": -5235870,\n \"details\": {}\n}" + }, + { + "name": "Liste des idées", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "[\n {\n \"id\": \"ad\",\n \"created_at\": \"2002-12-07T08:33:52.013Z\",\n \"title\": \"sint aliqua cupidatat\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"Duis velit\",\n \"votes_count\": -3329790,\n \"voters\": [\n \"amet\",\n \"L\"\n ],\n \"comments\": [\n {\n \"id\": \"Excepteur do labore ea\",\n \"created_at\": \"2002-03-17T20:08:27.710Z\",\n \"user_id\": \"id\",\n \"message\": \"enim labore ullamco mollit in\",\n \"images\": [\n \"http://fFplkkPQyjPs.skK,uu+MOD,O2OAUJiYAB8f98akpDuUqB8AFqBxTlhODC-Wu\",\n \"https://iQJQfuqRmRCm.zdwc9UKA9e.1k3pCbNUQIKFIHmOv7zjB\"\n ]\n },\n {\n \"id\": \"ut in qui minim\",\n \"created_at\": \"1985-06-24T16:11:14.687Z\",\n \"user_id\": \"dolore fugiat enim dolor\",\n \"message\": \"dolore cillum irure\",\n \"images\": [\n \"http://qZlkVaUbVSZay.osemOzVda7YXZ8P.NDyv,WR\",\n \"https://VmteLxMHkHmtuycANf.gjknMlPp-uvU0uDPb-FnlU62pLnGyT6EtvoOujKKM1ZIZ4SU\"\n ]\n }\n ],\n \"images\": [\n \"https://fxqsFabaDhtGDdE.pgtrJwqj\",\n \"https://UenRMqEwvZmxqZdkYxhcmuqJ.gxWlFkZxiMe0DR1wQhu\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n },\n {\n \"id\": \"aute nisi in pariatur\",\n \"created_at\": \"1962-12-07T02:49:38.536Z\",\n \"title\": \"incididunt\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"cupidatat officia ullamco\",\n \"votes_count\": -37490083,\n \"voters\": [\n \"cupidatat nulla cillum ad\",\n \"ea exercitation laborum Lorem\"\n ],\n \"comments\": [\n {\n \"id\": \"sit aliquip eu ea\",\n \"created_at\": \"1977-03-26T01:10:13.212Z\",\n \"user_id\": \"fugiat minim laborum\",\n \"message\": \"anim consequat sunt\",\n \"images\": [\n \"https://dTbqflreutw.llusk04c.U8f\",\n \"http://XHEKeSRbVhDNoCHwFYvYF.uhBR22-KXbuezQ,\"\n ]\n },\n {\n \"id\": \"proident reprehenderit sed in\",\n \"created_at\": \"1968-05-20T21:39:40.588Z\",\n \"user_id\": \"incididunt exercitation esse consectetur\",\n \"message\": \"ea officia culpa enim\",\n \"images\": [\n \"http://QIQkmpQYfDMfjSTaUXDTcyxSddzLCK.owsenSB33O5Io\",\n \"https://zcFfqO.vjpkQzd7VQEb9GG+GYuYRF,NaC50NnepKmf57j4NnWspIzTNHZ1LFRmg,CAcMdIpZMDJP-5Z\"\n ]\n }\n ],\n \"images\": [\n \"https://ZdGyKZrvdhyTLSqerYfLn.xvqjJjx0\",\n \"https://YNLgUBLpLfnTbrzMxefhWbdkXVkWh.osmoQDCTO2T3litUw38sB78degoH\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n }\n]" + } + ] + }, + { + "name": "Delete admin", + "request": { + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{token}}", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"user_email\": \"pouet@bncx.de\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/admin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "admin" + ] + } + }, + "response": [ + { + "name": "Erreur", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error_code\": \"est offic\",\n \"error_message\": \"labore Duis do aute\",\n \"error_http_code\": -5235870,\n \"details\": {}\n}" + }, + { + "name": "Liste des idées", + "originalRequest": { + "method": "GET", + "header": [ + { + "description": "Added as a part of security scheme: bearer", + "key": "Authorization", + "value": "Bearer " + } + ], + "url": { + "raw": "{{baseUrl}}/v1/ideas?page[number]=&page[size]=", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "ideas" + ], + "query": [ + { + "key": "page[number]", + "value": "" + }, + { + "key": "page[size]", + "value": "" + } + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "[\n {\n \"id\": \"ad\",\n \"created_at\": \"2002-12-07T08:33:52.013Z\",\n \"title\": \"sint aliqua cupidatat\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"Duis velit\",\n \"votes_count\": -3329790,\n \"voters\": [\n \"amet\",\n \"L\"\n ],\n \"comments\": [\n {\n \"id\": \"Excepteur do labore ea\",\n \"created_at\": \"2002-03-17T20:08:27.710Z\",\n \"user_id\": \"id\",\n \"message\": \"enim labore ullamco mollit in\",\n \"images\": [\n \"http://fFplkkPQyjPs.skK,uu+MOD,O2OAUJiYAB8f98akpDuUqB8AFqBxTlhODC-Wu\",\n \"https://iQJQfuqRmRCm.zdwc9UKA9e.1k3pCbNUQIKFIHmOv7zjB\"\n ]\n },\n {\n \"id\": \"ut in qui minim\",\n \"created_at\": \"1985-06-24T16:11:14.687Z\",\n \"user_id\": \"dolore fugiat enim dolor\",\n \"message\": \"dolore cillum irure\",\n \"images\": [\n \"http://qZlkVaUbVSZay.osemOzVda7YXZ8P.NDyv,WR\",\n \"https://VmteLxMHkHmtuycANf.gjknMlPp-uvU0uDPb-FnlU62pLnGyT6EtvoOujKKM1ZIZ4SU\"\n ]\n }\n ],\n \"images\": [\n \"https://fxqsFabaDhtGDdE.pgtrJwqj\",\n \"https://UenRMqEwvZmxqZdkYxhcmuqJ.gxWlFkZxiMe0DR1wQhu\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n },\n {\n \"id\": \"aute nisi in pariatur\",\n \"created_at\": \"1962-12-07T02:49:38.536Z\",\n \"title\": \"incididunt\",\n \"tag\": \"enhancement\",\n \"creator_id\": \"cupidatat officia ullamco\",\n \"votes_count\": -37490083,\n \"voters\": [\n \"cupidatat nulla cillum ad\",\n \"ea exercitation laborum Lorem\"\n ],\n \"comments\": [\n {\n \"id\": \"sit aliquip eu ea\",\n \"created_at\": \"1977-03-26T01:10:13.212Z\",\n \"user_id\": \"fugiat minim laborum\",\n \"message\": \"anim consequat sunt\",\n \"images\": [\n \"https://dTbqflreutw.llusk04c.U8f\",\n \"http://XHEKeSRbVhDNoCHwFYvYF.uhBR22-KXbuezQ,\"\n ]\n },\n {\n \"id\": \"proident reprehenderit sed in\",\n \"created_at\": \"1968-05-20T21:39:40.588Z\",\n \"user_id\": \"incididunt exercitation esse consectetur\",\n \"message\": \"ea officia culpa enim\",\n \"images\": [\n \"http://QIQkmpQYfDMfjSTaUXDTcyxSddzLCK.owsenSB33O5Io\",\n \"https://zcFfqO.vjpkQzd7VQEb9GG+GYuYRF,NaC50NnepKmf57j4NnWspIzTNHZ1LFRmg,CAcMdIpZMDJP-5Z\"\n ]\n }\n ],\n \"images\": [\n \"https://ZdGyKZrvdhyTLSqerYfLn.xvqjJjx0\",\n \"https://YNLgUBLpLfnTbrzMxefhWbdkXVkWh.osmoQDCTO2T3litUw38sB78degoH\"\n ],\n \"is_open\": true,\n \"user_has_voted\": false\n }\n]" + } + ] + } + ] } ], "auth": { From 97b80a52ec42234984d58fabc7c87e4373537994 Mon Sep 17 00:00:00 2001 From: Maxime Guilbert Date: Thu, 6 Nov 2025 07:28:02 -0500 Subject: [PATCH 2/2] feat: Add config to setup default admin accounts --- CHANGELOG.md | 1 + config.yaml | 3 + docs/configs.md | 12 ++ pkg/config/admin_models.go | 5 + pkg/config/models.go | 1 + .../admin/admin_management_service.go | 20 +++ .../admin/admin_management_service_test.go | 119 ++++++++++++++++-- 7 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 pkg/config/admin_models.go diff --git a/CHANGELOG.md b/CHANGELOG.md index dbe5fb3..3c5748f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - docs: Added license - feat: Add admin management endpoints +- feat: Add config to setup default admin accounts ### Changed - chore: Update dependencies diff --git a/config.yaml b/config.yaml index 954d117..cb18ed7 100644 --- a/config.yaml +++ b/config.yaml @@ -27,3 +27,6 @@ images: - png - jpg +admin: + defaultList: + - abc@gmail.com \ No newline at end of file diff --git a/docs/configs.md b/docs/configs.md index 36684fd..d99c5a4 100644 --- a/docs/configs.md +++ b/docs/configs.md @@ -73,3 +73,15 @@ images: - `images.maxImagesPerComment` : *(Env variable : `IMAGE_MAX_IMAGES_PER_COMMENT`)* - Max number of images per comment - `images.maxSize` : *(Env variable : `IMAGE_MAX_SIZE`)* - Image max site in bytes - `images.acceptedExtensions` : List of file extensions allowed for file update. + + +--- + +## Admin +```yaml +admin: + defaultList: +``` + +### Parameters +- `admin.defaultList` : List of default administrator of the Iris instance diff --git a/pkg/config/admin_models.go b/pkg/config/admin_models.go new file mode 100644 index 0000000..f8b1d6e --- /dev/null +++ b/pkg/config/admin_models.go @@ -0,0 +1,5 @@ +package config + +type AdminConfig struct { + DefaultList []string `yaml:"defaultList"` +} diff --git a/pkg/config/models.go b/pkg/config/models.go index a3ee76c..a15134f 100644 --- a/pkg/config/models.go +++ b/pkg/config/models.go @@ -6,4 +6,5 @@ type Config struct { Database DatabaseConfig `yaml:"database"` Server ServerConfig `yaml:"server"` Images ImageConfig `yaml:"images"` + Admin AdminConfig `yaml:"admin"` } diff --git a/pkg/services/admin/admin_management_service.go b/pkg/services/admin/admin_management_service.go index d3acd41..54c578a 100644 --- a/pkg/services/admin/admin_management_service.go +++ b/pkg/services/admin/admin_management_service.go @@ -3,6 +3,7 @@ package admin import ( "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" + "github.com/RoadTripMoustache/iris_api/pkg/config" dbmodels "github.com/RoadTripMoustache/iris_api/pkg/dbmodels/admin" "github.com/RoadTripMoustache/iris_api/pkg/enum" "github.com/RoadTripMoustache/iris_api/pkg/errors" @@ -13,6 +14,7 @@ import ( var ( noSQLStorageGetInstance = nosqlstorage.GetInstance + configGetConfigs = config.GetConfigs ) // GetAdmin retrieves the admin record for a user with the specified ID. @@ -24,6 +26,17 @@ var ( // - *dbmodels.Admin: The admin record if found, nil otherwise // - *errors.EnhancedError: Error information if the operation fails func GetAdmin(ctx utils.Context, userEmail string) (*dbmodels.Admin, *errors.EnhancedError) { + // Check in the default admins + cfg := configGetConfigs() + for _, a := range cfg.Admin.DefaultList { + if a == userEmail { + return &dbmodels.Admin{ + UserEmail: userEmail, + }, nil + } + } + + // Then check in the database requestFilters := []nosqlutils.Filter{{ Param: dbmodels.AdminUserEmailLabel, Operator: "==", @@ -60,6 +73,13 @@ func GetAdmins(ctx utils.Context) ([]*dbmodels.Admin, *errors.EnhancedError) { admins = append(admins, admin) } + cfg := configGetConfigs() + for _, a := range cfg.Admin.DefaultList { + admins = append(admins, &dbmodels.Admin{ + UserEmail: a, + }) + } + return admins, nil } diff --git a/pkg/services/admin/admin_management_service_test.go b/pkg/services/admin/admin_management_service_test.go index 22268d4..6420d0a 100644 --- a/pkg/services/admin/admin_management_service_test.go +++ b/pkg/services/admin/admin_management_service_test.go @@ -2,6 +2,7 @@ package admin import ( apiUtils "github.com/RoadTripMoustache/iris_api/pkg/apirouter/utils" + "github.com/RoadTripMoustache/iris_api/pkg/config" dbmodels "github.com/RoadTripMoustache/iris_api/pkg/dbmodels/admin" "github.com/RoadTripMoustache/iris_api/pkg/errors" "github.com/RoadTripMoustache/iris_api/pkg/mocks/services" @@ -10,6 +11,20 @@ import ( "testing" ) +var NoAdminConfig = config.Config{ + Admin: config.AdminConfig{ + DefaultList: []string{}, + }, +} + +var WithAdminConfig = config.Config{ + Admin: config.AdminConfig{ + DefaultList: []string{ + "toto@toto.com", + }, + }, +} + // ----- GetAdmin ----- // func Test_GetAdmin(t *testing.T) { testCases := []struct { @@ -18,45 +33,76 @@ func Test_GetAdmin(t *testing.T) { queryParams map[string][]string expectedResult *dbmodels.Admin exprectedErr *errors.EnhancedError + mockedConfig config.Config }{ { - caseDesc: "Empty DB", + caseDesc: "Empty DB and no default admin", dbResult: []map[string]interface{}{}, queryParams: nil, expectedResult: nil, exprectedErr: nil, + mockedConfig: NoAdminConfig, }, { - caseDesc: "Not empty DB", + caseDesc: "Not empty DB and no default admin", queryParams: nil, dbResult: []map[string]interface{}{ { - "user_email": "toto", + "user_email": "toto@toto.com", + }, + }, + expectedResult: &dbmodels.Admin{ + UserEmail: "toto@toto.com", + }, + exprectedErr: nil, + mockedConfig: NoAdminConfig, + }, + { + caseDesc: "Empty DB and with default admin", + dbResult: []map[string]interface{}{}, + queryParams: nil, + expectedResult: &dbmodels.Admin{ + UserEmail: "toto@toto.com", + }, + exprectedErr: nil, + mockedConfig: WithAdminConfig, + }, + { + caseDesc: "Not empty DB and with default admin", + queryParams: nil, + dbResult: []map[string]interface{}{ + { + "user_email": "toto@toto.com", }, }, expectedResult: &dbmodels.Admin{ - UserEmail: "toto", + UserEmail: "toto@toto.com", }, exprectedErr: nil, + mockedConfig: WithAdminConfig, }, } for _, testCase := range testCases { t.Run(testCase.caseDesc, func(t *testing.T) { // --- Given - userEmail := "toto_uuid" + userEmail := "toto@toto.com" ctx := apiUtils.Context{ UserEmail: userEmail, QueryParams: testCase.queryParams, } + configGetConfigs = func() config.Config { + return testCase.mockedConfig + } + mNoSQLStorageInstance := new(services.MockNoSQLStorageInstance) mNoSQLStorageInstance. On("GetFirstDocument", dbmodels.AdminCollectionName, []utils.Filter{{ Param: dbmodels.AdminUserEmailLabel, Operator: "==", - Value: "totoU", + Value: "toto@toto.com", }}). Return(testCase.dbResult) @@ -65,11 +111,13 @@ func Test_GetAdmin(t *testing.T) { noSQLStorageGetInstance = mockNoSQLStorageService.GetInstance // --- When - result, err := GetAdmin(ctx, "totoU") + result, err := GetAdmin(ctx, "toto@toto.com") // --- Then - mNoSQLStorageInstance.AssertExpectations(t) - mockNoSQLStorageService.AssertExpectations(t) + if len(testCase.mockedConfig.Admin.DefaultList) == 0 { + mNoSQLStorageInstance.AssertExpectations(t) + mockNoSQLStorageService.AssertExpectations(t) + } assert.Equal(t, testCase.exprectedErr, err) assert.Equal(t, testCase.expectedResult, result) }) @@ -84,16 +132,18 @@ func Test_GetAdmins(t *testing.T) { queryParams map[string][]string expectedResult []*dbmodels.Admin exprectedErr *errors.EnhancedError + mockedConfig config.Config }{ { - caseDesc: "Empty DB", + caseDesc: "Empty DB and no default admin", dbResult: []map[string]interface{}{}, queryParams: nil, expectedResult: nil, exprectedErr: nil, + mockedConfig: NoAdminConfig, }, { - caseDesc: "1 item", + caseDesc: "1 item in DB", queryParams: nil, dbResult: []map[string]interface{}{ { @@ -106,9 +156,10 @@ func Test_GetAdmins(t *testing.T) { }, }, exprectedErr: nil, + mockedConfig: NoAdminConfig, }, { - caseDesc: "2 items", + caseDesc: "2 items in DB", queryParams: nil, dbResult: []map[string]interface{}{ { @@ -127,13 +178,51 @@ func Test_GetAdmins(t *testing.T) { }, }, exprectedErr: nil, + mockedConfig: NoAdminConfig, + }, + { + caseDesc: "1 item in default admin", + queryParams: nil, + dbResult: nil, + expectedResult: []*dbmodels.Admin{ + { + UserEmail: "toto@toto.com", + }, + }, + exprectedErr: nil, + mockedConfig: WithAdminConfig, + }, + { + caseDesc: "2 items in DB and default admin", + queryParams: nil, + dbResult: []map[string]interface{}{ + { + "user_email": "toto", + }, + { + "user_email": "titi", + }, + }, + expectedResult: []*dbmodels.Admin{ + { + UserEmail: "toto", + }, + { + UserEmail: "titi", + }, + { + UserEmail: "toto@toto.com", + }, + }, + exprectedErr: nil, + mockedConfig: WithAdminConfig, }, } for _, testCase := range testCases { t.Run(testCase.caseDesc, func(t *testing.T) { // --- Given - userEmail := "toto_uuid" + userEmail := "toto@toto.com" pageNumber := 1 pageOffset := 0 ctx := apiUtils.Context{ @@ -155,6 +244,10 @@ func Test_GetAdmins(t *testing.T) { mockNoSQLStorageService.On("GetInstance").Return(mNoSQLStorageInstance) noSQLStorageGetInstance = mockNoSQLStorageService.GetInstance + configGetConfigs = func() config.Config { + return testCase.mockedConfig + } + // --- When result, err := GetAdmins(ctx)