From e0bfdd9a3798dd80cbec0978af368547ffa7ee5e Mon Sep 17 00:00:00 2001 From: Raymond Tukpe Date: Tue, 28 Jun 2022 22:44:28 +0100 Subject: [PATCH 1/8] Merge Release 0.6 into main (#811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: update changelog * Bump version to v0.6.0-rc * Release 0.6.0-rc.1 (#802) * Megre release-0.6 into main (#682) * feat: update changelog * Bump version to v0.6.0-rc * Updated Projects API (#684) * Update Groups API * Deprecate DefaultGroup * Update how integration tests are run * Deprecate immune tests * Change Duration to duration Co-authored-by: Raymond Tukpe Co-authored-by: Raymond Tukpe * Updated API to use defaults for both incoming and outgoing (#686) * Update Groups API * Deprecate DefaultGroup * Update how integration tests are run * Deprecate immune tests * Updated API to use defaults for both incoming and outgoing * Removed badger files * Setup cron system (#691) * Setup cron system * removed retry events schedule * add support for jwt authentication (#690) * add support for jwt authentication * feat: add support for blacklisting tokens and logout endpoint * chore: update route * add test for user repository * add user service test * add user integration test * add jwt test * add jwt realm test * chore: fix failing test * chore: add docs * chore: refactor jwt config to be standalone * update routes * chore: add duration comment * add ReplayAppEvent endpoint (#672) * feat: add ReplayAppEvent endpoint * tests: add tests * fix: specify wantErr * fix: change url to /events/{eventID/replay * tests: fix testdb.SeedEvent call Co-authored-by: Subomi Oluwalana * add crud for organisations (#685) * feat: add crud for organisations * feat: implement crud for organisations * feat: implement crud for organisations in BadgerDB * tests: add tests * tests: add integration build tags * tests: fix sorting * tests: fix sorting * tests: fix TestDeleteOrganisation * tests: fix tests * tests: fix tests * tests: add tests for organisation_service.go * tests: add organisation_integration_test.go * tests: add integration build tag * fix: add requireOrganisation to organisation sub route * tests: fix tests tests: add Test_UpdateOrganisation_EmptyOrganisationName & Test_CreateOrganisation_EmptyOrganisationName * tests: fix tests * fix: implement suggestions * tests: fix urls * fix initRealmChain call * docs: regenerate docs * Add missing comma to convoy.json.example (#700) * Generic Mailers Setup (#707) * Refactored mails * Removed test line * Removed hardcoded prefix * Enhancement: Refactor to use asynq queues (#704) * Feat: Refactor to use asynq queues * Add retry mechanism, clean up * Fix CI lint * Fix: parse redis url * Fix: redis dsn in client test * Add queue prometheus metrics * Chore: redis address in queue options * Chore: clean up consumer API * chore: add err checks Co-authored-by: Raymond Tukpe * Add subscriptions and sources (#683) * feat: add subscription resource * feat:m add subsciption repo tests * Merge branch 'main' of https://github.com/frain-dev/convoy into raymond/feat/add-subscriptions * feat: update subscription * chore: remove endpoint events * feat: update subscription schema and model * feat: use noemalised data modelling * feat: test outgoing event flow end to end * chore: add project/group type validation * complete UI rebuild (#681) * Ingestion API (#688) * Setup Ingestion API * Remove unnecessary line * check source type is HTTP before proceeding * feat: fix flow for incoming and outgoing events * Update process event delivery tests (#694) * chore: update process event delivery tests * chore: fix CI lint * chore: remove badger tests * chore: fix group repo tests * chore: update event delivery tests * chore: fix retry event delivery tests * chore: update FillGroupsStatistics and ForceRetryEventDeliveries tests * chore: add integration tag build directive * chore: fix integration tests * chore: implement PR feedback * chore: rename tests * Update subscription tests (#699) * chore: add LoadSubscriptionsPaged tests * feat: update mongodb indexes * chore: added create and update scubscription tests * chore: add delete scubscription tests * Add subscription integration tests (#701) * chore: add update and delete subscription tests * chore: add fetch all subscriptions test * Emmanuel/feature/new project structure (#689) * complete UI rebuild * connect apis for source * updated app and events for v2 * events/apps integration for v2 (#695) * events/apps integration for v2 * additional updates for app/events v2 * additional updates * additional ui updates for apps v2 * projects integration v2 * additional ui updates for v2 * Update projects page (#702) * show project type on projects page * undo style link * added copies for tooltips * updated copies for create projects * updated create app component * updated create projects * projects integration v2 (#696) * projects integration v2 * additional ui updates for v2 * Update projects page (#702) * show project type on projects page * undo style link * added copies for tooltips * updated copies for create projects * updated create app component * updated create projects * add spaces, 🥺 Co-authored-by: Emmanuel Aina * update on new app endpoint * additional fixes for apps * fixed events input focus * took out event required tag * Subscriptions UI (#705) * build subscriptions and create subscrips move project id to private service level * build subscriptions details * commit fix 1 * conflict fix * clean up * fixed create project json structure * build settings page (#706) Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * chore: remove extra subrouter * Merge main (#708) * Setup cron system (#691) * Setup cron system * removed retry events schedule * add support for jwt authentication (#690) * add support for jwt authentication * feat: add support for blacklisting tokens and logout endpoint * chore: update route * add test for user repository * add user service test * add user integration test * add jwt test * add jwt realm test * chore: fix failing test * chore: add docs * chore: refactor jwt config to be standalone * update routes * chore: add duration comment * add ReplayAppEvent endpoint (#672) * feat: add ReplayAppEvent endpoint * tests: add tests * fix: specify wantErr * fix: change url to /events/{eventID/replay * tests: fix testdb.SeedEvent call Co-authored-by: Subomi Oluwalana * add crud for organisations (#685) * feat: add crud for organisations * feat: implement crud for organisations * feat: implement crud for organisations in BadgerDB * tests: add tests * tests: add integration build tags * tests: fix sorting * tests: fix sorting * tests: fix TestDeleteOrganisation * tests: fix tests * tests: fix tests * tests: add tests for organisation_service.go * tests: add organisation_integration_test.go * tests: add integration build tag * fix: add requireOrganisation to organisation sub route * tests: fix tests tests: add Test_UpdateOrganisation_EmptyOrganisationName & Test_CreateOrganisation_EmptyOrganisationName * tests: fix tests * fix: implement suggestions * tests: fix urls * fix initRealmChain call * docs: regenerate docs * Add missing comma to convoy.json.example (#700) * chore: fixed tests and build Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort * Update date and time filters (#709) * Update styles source (#710) * Update date and time filters * update style source * chore: merge main into subscripions branch * chore: delete org tests Co-authored-by: Emmanuel Aina Co-authored-by: Subomi Oluwalana Co-authored-by: Pelumi Honey Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort * Enhancement: Asynq scheduler (#711) * Add asynq scheduler * Fix typo: ScheduleQueue * stop scheduler consumer * Combine task and task handler registration * Tie Users into organisations (#697) * feat: implement organisation member repository * feat: add metadata to auth.AuthenticatedUser * feat: add OrganisationInviteRepository * feat: add OrganisationMemberService & OrganisationInviteService * feat: add ErrEmptyBody * feat: add organisation invite handlers * tests: add tests for organisation_invite.go & organisation_member.go * fix: fix badger & orgMemberRepo * fix: fix badger * fix: initialise new repo * fix: fix organisation_service_test.go * tests: fix tests * tests: fix tests * tests: fix auth header * tests: fix OrganisationIntegrationTestSuite * tests: fix TestDeleteOrganisationInvite * tests: add organisation_member_service_test.go * fix: split ProcessOrganisationMemberInvite * tests: add more test cases to TestOrganisationInviteService_AcceptOrganisationMemberInvite * tests: add more test cases to TestOrganisationInviteService_AcceptOrganisationMemberInvite * fix: add organisationID param * fix: add organisation member routes * fix: seed superuser member for organisation owner * fix: fix doc * tests: add organisation_member_integration_test.go * fix: pass orgMemberRepo * fix: add pagination middleware to GetOrganisationMembers route * fix: add organisation_invite_integration_test.go * docs: fix docs * docs: fix owner_id json tag * fix: fix app queue param * tests: fix tests * fix: add unique email index for UserCollection * tests: seed organisation members * tests: panic on db connect error * tests: fix tests * tests: fix badger & DeleteOrganisationMember calls * tests: fix tests * fix: add LoadUserOrganisationsPaged * fix: fix LoadUserOrganisationsPaged pipleine * tests: fix Test_GetOrganisations * fix: require only token to process organisation invite * tests: increase TestOrganisationInviteService_ProcessOrganisationMemberInvite coverage * fix: validate new user * fix: move process invite route to ui * docs: define Organisation tag * feat: add invite expiry * tests: fix tests * Fixed Dockerfile (#722) * Update events and event deliveries payload (#720) * feat: add app metadata when fetching applications * feat: add metadata fields to event deliveries endpoint * chore: update tests * auth integration (#716) * auth integration * updates on organisation dropdwon * fixed http service bug * fixed http service bug * fix filters in events and event deliveries (#718) * fix filters in events and event deliveries * small touches * fix style source * fix all loaders in project page (#724) * Organisation settings ui (#719) * auth integration * organisations ui * organisations ui * updates on organisation dropdwon * updated settings page * fixed http service bug * fixed http service bug * took out billing * added delete organisation * added delete modal * chore: deprecate require auth (#728) * add user settings endpoints (#723) * feat: add user settings endpoints * chore: add user repository update test * chore: add user service test * chore: add user integration test * chore: add docs * feat: add user exists endpoint * Fixed ui build script (#730) * integrate email sender with organisation invite (#717) * feat: add invite email sending logic * feat: add organisation.invite.html * feat: - add TemplateName type - add more fields to Notification * feat: - add requireBaseUrl to /organisations route - use getUserFromContext * fix: move emailNotificationSender into preRun * feat: send invite email in new goroutine * feat: add notification task * feat: add notification task * tests: fix tests * refactor ui routes (#733) * refactor ui routes * add user routes * chore: fix failing test * chore: remove unused middleware for now * feat: add support for finding user by invite token * chore: remove user exists endpoint * chore: generate docs * chore: refactor user routes * chore: generate docs * Add subscription metadata (#738) * feat: add subscription metadata * feat: add metadata fields to event deliery * chore: remove useless internal function * feat: fix ingester event flow (#744) * fix: return correct error message for duplicate group name (#741) * Chore: remove example scheduler task (#745) * remove example scheduler task * Remove unwanted lines * Fix project creation onboarding (#726) * method for closing subscripton modal * add create subscription to project onboarding * update flow * connect project onboarding * fix project onboarding flow * update private services url * fix: source url (#747) * Fix update group reosurce and group service tests (#746) * feat: fix update group and service tests * feat: config is not required when creating a new project * patch: show app event count (#748) * Implement delete project (UI) (#749) * delete project update project onboarding * fix style source * updated subscriptions (#731) * updated subscriptions * updates on subscriptions * made subscription configs optional * review updates * tiny fixes * undo angular.json changes Co-authored-by: horlah * Enhancement: Alphanumeric secrets (#751) * Update GenerateRandomString * Add comments * Fix verifier config (#752) * prevent nil source verifier * changed ApiKey field names * apply validation to updatesource * fix: return correct error message for duplicate group name (#753) * link groups to organisations (#740) * feat: link groups to organisations * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * fix: - move security routes into ui - require organisation membership in order to create api key for a group - fix tests * fix: - fix security_integration_test.go - add orgID to SeedDefaultGroup * tests: fix tests * tests: fix tests * tests: fix tests Co-authored-by: Subomi Oluwalana * chore: add metadata to get one subscription (#757) * add tests for security logic change (#756) * tests: increase coverage * fix: call requireGroup middleware before requirePermission * doc: add doc duplicate * fix: - check GroupID in Test_CreateAppPortalAPIKey - add a descriptor to duplicate doc * fix: move key generation logic into SeedAPIKey * test: add Test_CreateAppPortalAPIKey_AppDoesNotBelongToGroup * fetch organisation member user info (#729) * feat: fetch organisation member user info * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * fix: unify loop * tests: defer closeFn * update subscriptions list (#755) * update subscriptions list * build update update subscription * Change "base_url" to "host" (#754) * feat: change "base_url" to "host" * chore: force commit * chore: update other places * chore: rename context function names * chore: fix typo * add fetch pending invites api (#736) * feat: add fetch pending invites api * feat: add fetch pending invites api * tests: fix tests Co-authored-by: Subomi Oluwalana * add support for analytics (#698) * feat: add support for analytics * feat: add support for configuration resource * chore: remove unused import * chore: add cron for tracking analytcis * feat: add config repository test * chore: add configuration service test * chore: add configuration integration test * feat: add api version to configuration response * chore: add analytics test * chore: generate docs * feat: use separate tokens based on environment * chore: add cron schedule * feat: add support for analytics source * chore: remove repeated org repo * feat: add org name to event details * feat: add support for tracking host * Feat: Forgot Password (#742) * add verification repo * merge main * Add password reset email notification * Add integration tests * update email template * set subject on notifications * Fix: Template params * Fix: correct url in email * Update internal/email/templates/reset.password.html Co-authored-by: Raymond Tukpe * Initialize reset token same line Co-authored-by: Raymond Tukpe * fixed basic auth check (#759) * app endpoint edit/update feature (#737) * app endpoint edit/update feature * updated apps and app-details * added empty state img for projects * tiny update * review updates * took out commented code * fixed oboarding flow * took out console.log Co-authored-by: horlah * Update source (#758) * event delivery batch retry (#735) * event delivery batch retry * fix for endpoint error * updated event deliveries * added tab to url * took out commented code * Fix event deliveries and deliveries attempt page (#763) * fix event deliveries and deliveries attempt page fix event deliveries in event page update text in create source form * delete commented code * fix: return EndpointError from SendNotification (#764) * fix: add invite token to find user by token response (#765) * fix: fix invite status update (#767) * New Relic Integration (#739) * New Relic Integration * removed temporary fix in middleware.go * Fixed redis instrumentation * Fixed failing test * fix subscription source fetching for outgoing group (#769) * fix: fix subscription source fetching for outgoing group * tests: fix tests * tests: fix tests * Fix: add subscription id on delete endpoint (#771) * Added missing HttpTimeout field (#762) * scope unique group names to organisation (#761) * fix: scope unique group names to organisation * tests: fix Test_CreateGroup * fix outgoing group event type matching (#768) * fix: fix outgoing group behaviour with * event type * tests: add TestProcessEventCreated * tests: fix TestProcessEventCreated * tests: fix TestProcessEventCreated * fix: fix badger subscriptionRepo * Teams Ui (#712) * teams ui * teams ui * invite team member integration * team management flow * took out projects from invite team member page * took out creatProjectComponent * change in adding filter to url * updated css link * added updates for teams * fixed space issue on table * dropdown fix * Fix roles and scope groups API (#773) * Fixed UI permissions * Fixed failing tests * Fixed Makefile * fixed go lint * User management (#766) * added public components, completed accept invite flow * forgot password flow * reset password service * added reset password * updated reset password * added account settings * updated accept invite * additional changes * added button loader gif * ui changes * added accepted inite status, added forgot password on login * Fixed Group Filters (#774) * fix organisation invite template (#760) * docs" fix docs * fix: template * fix: fix error messages * add document_status filter to all find queries (#725) * fix: add document_status to all find queries * tests: fix tests * remove mongo dsn * tests: fix tests * tests: fix tests Co-authored-by: Subomi Oluwalana * fix organisation switching (#775) delete organisation in localstorage on logout refresh page on create new organisation to set that organisation fix create source * Fe bug fixes (#772) * bug fixes for apps and subscruptions * added loaders for app/event-delivery details * fixed app details loader * review fixes * took out async * Chore: clean up reset-password (#776) * Remove email from request, make reset_password_token unique * Fix CI tests * ignore token json * Build new app portal page (#770) * build new app portal page * enable delete and update subscription on app portal * fix event deliveries clear filter * build support with app portal sdk * reset style source * fix: use correct arguments for api key verifier (#779) * validate app, endpoint & source when creating subscription (#778) * fix: validate app & endpoint when creating subscription * tests: add tests * tests: fix tests * fix: validate incoming group source when creating subscription * tests: fix tests * tests: fix tests * fix: prevent organisation owner from being deactivated (#781) * feat: set default event types when filter config is nil (#783) * Add resend and cancel org invite endpoints (#782) * Add resend and cancel invite endpoints * Scope endpoints to invite resource * Move website (#785) * delete website * move website out * add toggle subscription status endpoint (#784) * feat: add toggle subscription status endpoint * feat: add toggle subscription status endpoint * fix: add default config for subscription (#787) * chore: change app portal link (#788) * Revert "chore: change app portal link (#788)" (#790) This reverts commit afdf3f2b84508af8f4e0b58442a462f89407aff9. * Add Custom source: Github (#791) * Added custom source: Github * Fixed failing tests * Removed unwanted line * support github custom ingester (#792) * Fixed a race condition that could occur when creating an application endpoint (#793) * fix: fixed a race condition that could occur when creating an application endpoint * chore: update tests * bugfixes for v6 (#786) * fixed project update error * removed email from reset password * copy changes, forgot password validation * updated create subscription form * added analytics * user redirect to dashboard on accepting invite * team invites updates * additional changes * moved analytics modal to middle * moved analytics modal to middle * updated analytics modal * app delete feature * updated delete app * review updates * review updates * updated org switch * feat: updated changelog Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort Co-authored-by: Ogban Ugot Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * chore: prefer npm ci when installing nodejs dependecies (#803) * Bump version to v0.6.0-rc.1 * chore: revert makefile ui build command * Update release branch v0.6 (#810) * chore: update readme with latest image (#805) * Merge Release 0.6 into main (#804) * feat: update changelog * Bump version to v0.6.0-rc * Release 0.6.0-rc.1 (#802) * Megre release-0.6 into main (#682) * feat: update changelog * Bump version to v0.6.0-rc * Updated Projects API (#684) * Update Groups API * Deprecate DefaultGroup * Update how integration tests are run * Deprecate immune tests * Change Duration to duration Co-authored-by: Raymond Tukpe Co-authored-by: Raymond Tukpe * Updated API to use defaults for both incoming and outgoing (#686) * Update Groups API * Deprecate DefaultGroup * Update how integration tests are run * Deprecate immune tests * Updated API to use defaults for both incoming and outgoing * Removed badger files * Setup cron system (#691) * Setup cron system * removed retry events schedule * add support for jwt authentication (#690) * add support for jwt authentication * feat: add support for blacklisting tokens and logout endpoint * chore: update route * add test for user repository * add user service test * add user integration test * add jwt test * add jwt realm test * chore: fix failing test * chore: add docs * chore: refactor jwt config to be standalone * update routes * chore: add duration comment * add ReplayAppEvent endpoint (#672) * feat: add ReplayAppEvent endpoint * tests: add tests * fix: specify wantErr * fix: change url to /events/{eventID/replay * tests: fix testdb.SeedEvent call Co-authored-by: Subomi Oluwalana * add crud for organisations (#685) * feat: add crud for organisations * feat: implement crud for organisations * feat: implement crud for organisations in BadgerDB * tests: add tests * tests: add integration build tags * tests: fix sorting * tests: fix sorting * tests: fix TestDeleteOrganisation * tests: fix tests * tests: fix tests * tests: add tests for organisation_service.go * tests: add organisation_integration_test.go * tests: add integration build tag * fix: add requireOrganisation to organisation sub route * tests: fix tests tests: add Test_UpdateOrganisation_EmptyOrganisationName & Test_CreateOrganisation_EmptyOrganisationName * tests: fix tests * fix: implement suggestions * tests: fix urls * fix initRealmChain call * docs: regenerate docs * Add missing comma to convoy.json.example (#700) * Generic Mailers Setup (#707) * Refactored mails * Removed test line * Removed hardcoded prefix * Enhancement: Refactor to use asynq queues (#704) * Feat: Refactor to use asynq queues * Add retry mechanism, clean up * Fix CI lint * Fix: parse redis url * Fix: redis dsn in client test * Add queue prometheus metrics * Chore: redis address in queue options * Chore: clean up consumer API * chore: add err checks Co-authored-by: Raymond Tukpe * Add subscriptions and sources (#683) * feat: add subscription resource * feat:m add subsciption repo tests * Merge branch 'main' of https://github.com/frain-dev/convoy into raymond/feat/add-subscriptions * feat: update subscription * chore: remove endpoint events * feat: update subscription schema and model * feat: use noemalised data modelling * feat: test outgoing event flow end to end * chore: add project/group type validation * complete UI rebuild (#681) * Ingestion API (#688) * Setup Ingestion API * Remove unnecessary line * check source type is HTTP before proceeding * feat: fix flow for incoming and outgoing events * Update process event delivery tests (#694) * chore: update process event delivery tests * chore: fix CI lint * chore: remove badger tests * chore: fix group repo tests * chore: update event delivery tests * chore: fix retry event delivery tests * chore: update FillGroupsStatistics and ForceRetryEventDeliveries tests * chore: add integration tag build directive * chore: fix integration tests * chore: implement PR feedback * chore: rename tests * Update subscription tests (#699) * chore: add LoadSubscriptionsPaged tests * feat: update mongodb indexes * chore: added create and update scubscription tests * chore: add delete scubscription tests * Add subscription integration tests (#701) * chore: add update and delete subscription tests * chore: add fetch all subscriptions test * Emmanuel/feature/new project structure (#689) * complete UI rebuild * connect apis for source * updated app and events for v2 * events/apps integration for v2 (#695) * events/apps integration for v2 * additional updates for app/events v2 * additional updates * additional ui updates for apps v2 * projects integration v2 * additional ui updates for v2 * Update projects page (#702) * show project type on projects page * undo style link * added copies for tooltips * updated copies for create projects * updated create app component * updated create projects * projects integration v2 (#696) * projects integration v2 * additional ui updates for v2 * Update projects page (#702) * show project type on projects page * undo style link * added copies for tooltips * updated copies for create projects * updated create app component * updated create projects * add spaces, 🥺 Co-authored-by: Emmanuel Aina * update on new app endpoint * additional fixes for apps * fixed events input focus * took out event required tag * Subscriptions UI (#705) * build subscriptions and create subscrips move project id to private service level * build subscriptions details * commit fix 1 * conflict fix * clean up * fixed create project json structure * build settings page (#706) Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * chore: remove extra subrouter * Merge main (#708) * Setup cron system (#691) * Setup cron system * removed retry events schedule * add support for jwt authentication (#690) * add support for jwt authentication * feat: add support for blacklisting tokens and logout endpoint * chore: update route * add test for user repository * add user service test * add user integration test * add jwt test * add jwt realm test * chore: fix failing test * chore: add docs * chore: refactor jwt config to be standalone * update routes * chore: add duration comment * add ReplayAppEvent endpoint (#672) * feat: add ReplayAppEvent endpoint * tests: add tests * fix: specify wantErr * fix: change url to /events/{eventID/replay * tests: fix testdb.SeedEvent call Co-authored-by: Subomi Oluwalana * add crud for organisations (#685) * feat: add crud for organisations * feat: implement crud for organisations * feat: implement crud for organisations in BadgerDB * tests: add tests * tests: add integration build tags * tests: fix sorting * tests: fix sorting * tests: fix TestDeleteOrganisation * tests: fix tests * tests: fix tests * tests: add tests for organisation_service.go * tests: add organisation_integration_test.go * tests: add integration build tag * fix: add requireOrganisation to organisation sub route * tests: fix tests tests: add Test_UpdateOrganisation_EmptyOrganisationName & Test_CreateOrganisation_EmptyOrganisationName * tests: fix tests * fix: implement suggestions * tests: fix urls * fix initRealmChain call * docs: regenerate docs * Add missing comma to convoy.json.example (#700) * chore: fixed tests and build Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort * Update date and time filters (#709) * Update styles source (#710) * Update date and time filters * update style source * chore: merge main into subscripions branch * chore: delete org tests Co-authored-by: Emmanuel Aina Co-authored-by: Subomi Oluwalana Co-authored-by: Pelumi Honey Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort * Enhancement: Asynq scheduler (#711) * Add asynq scheduler * Fix typo: ScheduleQueue * stop scheduler consumer * Combine task and task handler registration * Tie Users into organisations (#697) * feat: implement organisation member repository * feat: add metadata to auth.AuthenticatedUser * feat: add OrganisationInviteRepository * feat: add OrganisationMemberService & OrganisationInviteService * feat: add ErrEmptyBody * feat: add organisation invite handlers * tests: add tests for organisation_invite.go & organisation_member.go * fix: fix badger & orgMemberRepo * fix: fix badger * fix: initialise new repo * fix: fix organisation_service_test.go * tests: fix tests * tests: fix tests * tests: fix auth header * tests: fix OrganisationIntegrationTestSuite * tests: fix TestDeleteOrganisationInvite * tests: add organisation_member_service_test.go * fix: split ProcessOrganisationMemberInvite * tests: add more test cases to TestOrganisationInviteService_AcceptOrganisationMemberInvite * tests: add more test cases to TestOrganisationInviteService_AcceptOrganisationMemberInvite * fix: add organisationID param * fix: add organisation member routes * fix: seed superuser member for organisation owner * fix: fix doc * tests: add organisation_member_integration_test.go * fix: pass orgMemberRepo * fix: add pagination middleware to GetOrganisationMembers route * fix: add organisation_invite_integration_test.go * docs: fix docs * docs: fix owner_id json tag * fix: fix app queue param * tests: fix tests * fix: add unique email index for UserCollection * tests: seed organisation members * tests: panic on db connect error * tests: fix tests * tests: fix badger & DeleteOrganisationMember calls * tests: fix tests * fix: add LoadUserOrganisationsPaged * fix: fix LoadUserOrganisationsPaged pipleine * tests: fix Test_GetOrganisations * fix: require only token to process organisation invite * tests: increase TestOrganisationInviteService_ProcessOrganisationMemberInvite coverage * fix: validate new user * fix: move process invite route to ui * docs: define Organisation tag * feat: add invite expiry * tests: fix tests * Fixed Dockerfile (#722) * Update events and event deliveries payload (#720) * feat: add app metadata when fetching applications * feat: add metadata fields to event deliveries endpoint * chore: update tests * auth integration (#716) * auth integration * updates on organisation dropdwon * fixed http service bug * fixed http service bug * fix filters in events and event deliveries (#718) * fix filters in events and event deliveries * small touches * fix style source * fix all loaders in project page (#724) * Organisation settings ui (#719) * auth integration * organisations ui * organisations ui * updates on organisation dropdwon * updated settings page * fixed http service bug * fixed http service bug * took out billing * added delete organisation * added delete modal * chore: deprecate require auth (#728) * add user settings endpoints (#723) * feat: add user settings endpoints * chore: add user repository update test * chore: add user service test * chore: add user integration test * chore: add docs * feat: add user exists endpoint * Fixed ui build script (#730) * integrate email sender with organisation invite (#717) * feat: add invite email sending logic * feat: add organisation.invite.html * feat: - add TemplateName type - add more fields to Notification * feat: - add requireBaseUrl to /organisations route - use getUserFromContext * fix: move emailNotificationSender into preRun * feat: send invite email in new goroutine * feat: add notification task * feat: add notification task * tests: fix tests * refactor ui routes (#733) * refactor ui routes * add user routes * chore: fix failing test * chore: remove unused middleware for now * feat: add support for finding user by invite token * chore: remove user exists endpoint * chore: generate docs * chore: refactor user routes * chore: generate docs * Add subscription metadata (#738) * feat: add subscription metadata * feat: add metadata fields to event deliery * chore: remove useless internal function * feat: fix ingester event flow (#744) * fix: return correct error message for duplicate group name (#741) * Chore: remove example scheduler task (#745) * remove example scheduler task * Remove unwanted lines * Fix project creation onboarding (#726) * method for closing subscripton modal * add create subscription to project onboarding * update flow * connect project onboarding * fix project onboarding flow * update private services url * fix: source url (#747) * Fix update group reosurce and group service tests (#746) * feat: fix update group and service tests * feat: config is not required when creating a new project * patch: show app event count (#748) * Implement delete project (UI) (#749) * delete project update project onboarding * fix style source * updated subscriptions (#731) * updated subscriptions * updates on subscriptions * made subscription configs optional * review updates * tiny fixes * undo angular.json changes Co-authored-by: horlah * Enhancement: Alphanumeric secrets (#751) * Update GenerateRandomString * Add comments * Fix verifier config (#752) * prevent nil source verifier * changed ApiKey field names * apply validation to updatesource * fix: return correct error message for duplicate group name (#753) * link groups to organisations (#740) * feat: link groups to organisations * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * fix: - move security routes into ui - require organisation membership in order to create api key for a group - fix tests * fix: - fix security_integration_test.go - add orgID to SeedDefaultGroup * tests: fix tests * tests: fix tests * tests: fix tests Co-authored-by: Subomi Oluwalana * chore: add metadata to get one subscription (#757) * add tests for security logic change (#756) * tests: increase coverage * fix: call requireGroup middleware before requirePermission * doc: add doc duplicate * fix: - check GroupID in Test_CreateAppPortalAPIKey - add a descriptor to duplicate doc * fix: move key generation logic into SeedAPIKey * test: add Test_CreateAppPortalAPIKey_AppDoesNotBelongToGroup * fetch organisation member user info (#729) * feat: fetch organisation member user info * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * tests: fix tests * fix: unify loop * tests: defer closeFn * update subscriptions list (#755) * update subscriptions list * build update update subscription * Change "base_url" to "host" (#754) * feat: change "base_url" to "host" * chore: force commit * chore: update other places * chore: rename context function names * chore: fix typo * add fetch pending invites api (#736) * feat: add fetch pending invites api * feat: add fetch pending invites api * tests: fix tests Co-authored-by: Subomi Oluwalana * add support for analytics (#698) * feat: add support for analytics * feat: add support for configuration resource * chore: remove unused import * chore: add cron for tracking analytcis * feat: add config repository test * chore: add configuration service test * chore: add configuration integration test * feat: add api version to configuration response * chore: add analytics test * chore: generate docs * feat: use separate tokens based on environment * chore: add cron schedule * feat: add support for analytics source * chore: remove repeated org repo * feat: add org name to event details * feat: add support for tracking host * Feat: Forgot Password (#742) * add verification repo * merge main * Add password reset email notification * Add integration tests * update email template * set subject on notifications * Fix: Template params * Fix: correct url in email * Update internal/email/templates/reset.password.html Co-authored-by: Raymond Tukpe * Initialize reset token same line Co-authored-by: Raymond Tukpe * fixed basic auth check (#759) * app endpoint edit/update feature (#737) * app endpoint edit/update feature * updated apps and app-details * added empty state img for projects * tiny update * review updates * took out commented code * fixed oboarding flow * took out console.log Co-authored-by: horlah * Update source (#758) * event delivery batch retry (#735) * event delivery batch retry * fix for endpoint error * updated event deliveries * added tab to url * took out commented code * Fix event deliveries and deliveries attempt page (#763) * fix event deliveries and deliveries attempt page fix event deliveries in event page update text in create source form * delete commented code * fix: return EndpointError from SendNotification (#764) * fix: add invite token to find user by token response (#765) * fix: fix invite status update (#767) * New Relic Integration (#739) * New Relic Integration * removed temporary fix in middleware.go * Fixed redis instrumentation * Fixed failing test * fix subscription source fetching for outgoing group (#769) * fix: fix subscription source fetching for outgoing group * tests: fix tests * tests: fix tests * Fix: add subscription id on delete endpoint (#771) * Added missing HttpTimeout field (#762) * scope unique group names to organisation (#761) * fix: scope unique group names to organisation * tests: fix Test_CreateGroup * fix outgoing group event type matching (#768) * fix: fix outgoing group behaviour with * event type * tests: add TestProcessEventCreated * tests: fix TestProcessEventCreated * tests: fix TestProcessEventCreated * fix: fix badger subscriptionRepo * Teams Ui (#712) * teams ui * teams ui * invite team member integration * team management flow * took out projects from invite team member page * took out creatProjectComponent * change in adding filter to url * updated css link * added updates for teams * fixed space issue on table * dropdown fix * Fix roles and scope groups API (#773) * Fixed UI permissions * Fixed failing tests * Fixed Makefile * fixed go lint * User management (#766) * added public components, completed accept invite flow * forgot password flow * reset password service * added reset password * updated reset password * added account settings * updated accept invite * additional changes * added button loader gif * ui changes * added accepted inite status, added forgot password on login * Fixed Group Filters (#774) * fix organisation invite template (#760) * docs" fix docs * fix: template * fix: fix error messages * add document_status filter to all find queries (#725) * fix: add document_status to all find queries * tests: fix tests * remove mongo dsn * tests: fix tests * tests: fix tests Co-authored-by: Subomi Oluwalana * fix organisation switching (#775) delete organisation in localstorage on logout refresh page on create new organisation to set that organisation fix create source * Fe bug fixes (#772) * bug fixes for apps and subscruptions * added loaders for app/event-delivery details * fixed app details loader * review fixes * took out async * Chore: clean up reset-password (#776) * Remove email from request, make reset_password_token unique * Fix CI tests * ignore token json * Build new app portal page (#770) * build new app portal page * enable delete and update subscription on app portal * fix event deliveries clear filter * build support with app portal sdk * reset style source * fix: use correct arguments for api key verifier (#779) * validate app, endpoint & source when creating subscription (#778) * fix: validate app & endpoint when creating subscription * tests: add tests * tests: fix tests * fix: validate incoming group source when creating subscription * tests: fix tests * tests: fix tests * fix: prevent organisation owner from being deactivated (#781) * feat: set default event types when filter config is nil (#783) * Add resend and cancel org invite endpoints (#782) * Add resend and cancel invite endpoints * Scope endpoints to invite resource * Move website (#785) * delete website * move website out * add toggle subscription status endpoint (#784) * feat: add toggle subscription status endpoint * feat: add toggle subscription status endpoint * fix: add default config for subscription (#787) * chore: change app portal link (#788) * Revert "chore: change app portal link (#788)" (#790) This reverts commit afdf3f2b84508af8f4e0b58442a462f89407aff9. * Add Custom source: Github (#791) * Added custom source: Github * Fixed failing tests * Removed unwanted line * support github custom ingester (#792) * Fixed a race condition that could occur when creating an application endpoint (#793) * fix: fixed a race condition that could occur when creating an application endpoint * chore: update tests * bugfixes for v6 (#786) * fixed project update error * removed email from reset password * copy changes, forgot password validation * updated create subscription form * added analytics * user redirect to dashboard on accepting invite * team invites updates * additional changes * moved analytics modal to middle * moved analytics modal to middle * updated analytics modal * app delete feature * updated delete app * review updates * review updates * updated org switch * feat: updated changelog Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort Co-authored-by: Ogban Ugot Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * chore: prefer npm ci when installing nodejs dependecies (#803) * Bump version to v0.6.0-rc.1 * chore: revert makefile ui build command Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort Co-authored-by: Ogban Ugot Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * Refactor DB Layer (#780) * feat: add db store file * feat: refactor some groyp repo methods * Refactor event repo, group repo tests * group and event tests * fix IsValidPointer, refactor organization repos (#794) * feat: refactor config repo to use store (#798) * feat: refactor user repo to use store (#797) * refactor subscriptions repo (#795) * feat: refactor subscriptions repo * tests: fix test * tests: fix test * refactor applications repo (#799) * feat: refactor app repo * fix: fix call * fix: remove ==== * tests: fix test * refactor source repo (#796) * feat: refactor source repo to use store * fix: update find one pointer check * chore: fix lint error * fix: clean up db.go Co-authored-by: ogbanugot Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu * chore: rename (#806) * Fix: use redis client (#807) * fix: use dereference slice (#808) * Ui Fixes (#809) * updated analytics modal * fix for creating organisation * fix fecth apps on create subscriptions oage * fix: update sources * updated create/update endpoint form * updated app details for incoming projects * updated create subscriptions for app portal * updated create projects form * removed console.log, updated project type Co-authored-by: Dotun Jolaoso Co-authored-by: Raymond Tukpe Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort Co-authored-by: Ogban Ugot Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey * Updated changelog for v0.6.0-rc.2 * Bump version to v0.6.0-rc.2 Co-authored-by: Subomi Oluwalana Co-authored-by: Dotun Jolaoso Co-authored-by: Daniel Oluojomu Co-authored-by: Daniel Perrefort Co-authored-by: Ogban Ugot Co-authored-by: Emmanuel Aina Co-authored-by: Pelumi Honey --- CHANGELOG.md | 8 ++++++++ VERSION | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2646c6962..590aad190e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## v0.6.0-rc.2 + +- [Bugfix] Dereference slice when finding source subscriptions #808 +- [Bugfix] Use redis client in scheduler #807 +- [Bugfix] Fixed an issue where the source type would not be updated when updating a Github source +- [Bugfix] Fixed an issue where the application details would not be loaded when creating a subscription +- [Bugfix] Fixed an issue where an organization created by a user would not show on the top bar to be selected + ## v0.6.0-rc.1 - [Change] Introduce organisations to partition different sets of projects. diff --git a/VERSION b/VERSION index 01b366027c..3c3b5ba413 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.6.0-rc.1 +v0.6.0-rc.2 From fb1ef9789c166b9aa7b61acee9e05499c8aa6fc7 Mon Sep 17 00:00:00 2001 From: Ogban Ugot Date: Wed, 29 Jun 2022 11:57:48 +0100 Subject: [PATCH 2/8] Enhancement: add cancelled status on org invite (#812) * Enhancement: add cancelled status on org invite --- datastore/models.go | 7 ++-- docs/docs.go | 37 +++++++++++++++++-- docs/swagger.json | 34 ++++++++++++++++- docs/swagger.yaml | 23 +++++++++++- docs/v3/openapi3.json | 34 ++++++++++++++++- docs/v3/openapi3.yaml | 23 +++++++++++- server/organisation_invite.go | 6 +-- .../organisation_invite_integration_test.go | 5 +++ services/organisation_invite_service.go | 14 ++++--- services/organisation_invite_service_test.go | 16 +++++++- 10 files changed, 178 insertions(+), 21 deletions(-) diff --git a/datastore/models.go b/datastore/models.go index 2fa312bd8c..5d3d773fd7 100644 --- a/datastore/models.go +++ b/datastore/models.go @@ -604,9 +604,10 @@ type UserMetadata struct { type InviteStatus string const ( - InviteStatusAccepted InviteStatus = "accepted" - InviteStatusDeclined InviteStatus = "declined" - InviteStatusPending InviteStatus = "pending" + InviteStatusAccepted InviteStatus = "accepted" + InviteStatusDeclined InviteStatus = "declined" + InviteStatusPending InviteStatus = "pending" + InviteStatusCancelled InviteStatus = "cancelled" ) func (i InviteStatus) String() string { diff --git a/docs/docs.go b/docs/docs.go index 0b3f4d048f..cd6797bae0 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,7 +1,6 @@ // Package docs GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2022-06-23 16:01:47.052769 +0100 WAT m=+108.083357501 - +// 2022-06-29 11:49:25.843025 +0100 WAT m=+110.342946709 package docs import ( @@ -6145,7 +6144,7 @@ var doc = `{ "type": "object", "properties": { "data": { - "$ref": "#/definitions/server.Stub" + "$ref": "#/definitions/datastore.OrganisationInvite" } } } @@ -8474,6 +8473,38 @@ var doc = `{ } } }, + "datastore.OrganisationInvite": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "deleted_at": { + "type": "string" + }, + "invitee_email": { + "type": "string" + }, + "organisation_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/auth.Role" + }, + "status": { + "type": "string" + }, + "token": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "datastore.OrganisationMember": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index e501f2a2ba..054c936863 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -6132,7 +6132,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/definitions/server.Stub" + "$ref": "#/definitions/datastore.OrganisationInvite" } } } @@ -8461,6 +8461,38 @@ } } }, + "datastore.OrganisationInvite": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "deleted_at": { + "type": "string" + }, + "invitee_email": { + "type": "string" + }, + "organisation_id": { + "type": "string" + }, + "role": { + "$ref": "#/definitions/auth.Role" + }, + "status": { + "type": "string" + }, + "token": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + } + }, "datastore.OrganisationMember": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index d93055b698..c54b6b138e 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -322,6 +322,27 @@ definitions: updated_at: type: string type: object + datastore.OrganisationInvite: + properties: + created_at: + type: string + deleted_at: + type: string + invitee_email: + type: string + organisation_id: + type: string + role: + $ref: '#/definitions/auth.Role' + status: + type: string + token: + type: string + uid: + type: string + updated_at: + type: string + type: object datastore.OrganisationMember: properties: created_at: @@ -3991,7 +4012,7 @@ paths: - $ref: '#/definitions/server.serverResponse' - properties: data: - $ref: '#/definitions/server.Stub' + $ref: '#/definitions/datastore.OrganisationInvite' type: object "400": description: Bad Request diff --git a/docs/v3/openapi3.json b/docs/v3/openapi3.json index 570810a2f1..6d89d501b8 100644 --- a/docs/v3/openapi3.json +++ b/docs/v3/openapi3.json @@ -474,6 +474,38 @@ }, "type": "object" }, + "datastore.OrganisationInvite": { + "properties": { + "created_at": { + "type": "string" + }, + "deleted_at": { + "type": "string" + }, + "invitee_email": { + "type": "string" + }, + "organisation_id": { + "type": "string" + }, + "role": { + "$ref": "#/components/schemas/auth.Role" + }, + "status": { + "type": "string" + }, + "token": { + "type": "string" + }, + "uid": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "type": "object" + }, "datastore.OrganisationMember": { "properties": { "created_at": { @@ -8091,7 +8123,7 @@ { "properties": { "data": { - "$ref": "#/components/schemas/server.Stub" + "$ref": "#/components/schemas/datastore.OrganisationInvite" } }, "type": "object" diff --git a/docs/v3/openapi3.yaml b/docs/v3/openapi3.yaml index 5a0786fcc9..b2351dfff8 100644 --- a/docs/v3/openapi3.yaml +++ b/docs/v3/openapi3.yaml @@ -322,6 +322,27 @@ components: updated_at: type: string type: object + datastore.OrganisationInvite: + properties: + created_at: + type: string + deleted_at: + type: string + invitee_email: + type: string + organisation_id: + type: string + role: + $ref: '#/components/schemas/auth.Role' + status: + type: string + token: + type: string + uid: + type: string + updated_at: + type: string + type: object datastore.OrganisationMember: properties: created_at: @@ -4325,7 +4346,7 @@ paths: - $ref: '#/components/schemas/server.serverResponse' - properties: data: - $ref: '#/components/schemas/server.Stub' + $ref: '#/components/schemas/datastore.OrganisationInvite' type: object description: OK "400": diff --git a/server/organisation_invite.go b/server/organisation_invite.go index 033b14546b..e3c4c7a64c 100644 --- a/server/organisation_invite.go +++ b/server/organisation_invite.go @@ -176,17 +176,17 @@ func (a *applicationHandler) ResendOrganizationInvite(w http.ResponseWriter, r * // @Produce json // @Param orgID path string true "organisation id" // @Param inviteID path string true "invite id" -// @Success 200 {object} serverResponse{data=Stub} +// @Success 200 {object} serverResponse{data=datastore.OrganisationInvite} // @Failure 400,401,500 {object} serverResponse{data=Stub} // @Security ApiKeyAuth // @Router /ui/organisations/{orgID}/invites/{inviteID}/cancel [post] func (a *applicationHandler) CancelOrganizationInvite(w http.ResponseWriter, r *http.Request) { - err := a.organisationInviteService.CancelOrganisationMemberInvite(r.Context(), chi.URLParam(r, "inviteID")) + iv, err := a.organisationInviteService.CancelOrganisationMemberInvite(r.Context(), chi.URLParam(r, "inviteID")) if err != nil { log.WithError(err).Error("failed to cancel organisation member invite") _ = render.Render(w, r, newServiceErrResponse(err)) return } - _ = render.Render(w, r, newServerResponse("invite cancelled successfully", nil, http.StatusOK)) + _ = render.Render(w, r, newServerResponse("invite cancelled successfully", iv, http.StatusOK)) } diff --git a/server/organisation_invite_integration_test.go b/server/organisation_invite_integration_test.go index de67e075bf..80177d031a 100644 --- a/server/organisation_invite_integration_test.go +++ b/server/organisation_invite_integration_test.go @@ -436,6 +436,11 @@ func (s *OrganisationInviteIntegrationTestSuite) Test_CancelInvite() { s.Router.ServeHTTP(w, req) require.Equal(s.T(), http.StatusOK, w.Code) + + var response datastore.OrganisationInvite + parseResponse(s.T(), w.Result(), &response) + require.Equal(s.T(), datastore.InviteStatusCancelled, response.Status) + } func TestOrganisationInviteIntegrationTestSuite(t *testing.T) { diff --git a/services/organisation_invite_service.go b/services/organisation_invite_service.go index 34c6672fdb..032a6e63b4 100644 --- a/services/organisation_invite_service.go +++ b/services/organisation_invite_service.go @@ -257,17 +257,19 @@ func (ois *OrganisationInviteService) ResendOrganisationMemberInvite(ctx context return iv, nil } -func (ois *OrganisationInviteService) CancelOrganisationMemberInvite(ctx context.Context, inviteID string) error { +func (ois *OrganisationInviteService) CancelOrganisationMemberInvite(ctx context.Context, inviteID string) (*datastore.OrganisationInvite, error) { iv, err := ois.orgInviteRepo.FetchOrganisationInviteByID(ctx, inviteID) if err != nil { log.WithError(err).Error("failed to fetch organisation by invitee id") - return NewServiceError(http.StatusBadRequest, errors.New("failed to fetch organisation by invitee id")) + return nil, NewServiceError(http.StatusBadRequest, errors.New("failed to fetch organisation by invitee id")) } - err = ois.orgInviteRepo.DeleteOrganisationInvite(ctx, iv.UID) + iv.Status = datastore.InviteStatusCancelled + + err = ois.orgInviteRepo.UpdateOrganisationInvite(ctx, iv) if err != nil { - log.WithError(err).Error("failed to delete organisation invite") - return NewServiceError(http.StatusBadRequest, errors.New("failed to delete organisation invite")) + log.WithError(err).Error("failed to update organisation member invite") + return nil, NewServiceError(http.StatusBadRequest, errors.New("failed to update organisation member invite")) } - return nil + return iv, nil } diff --git a/services/organisation_invite_service_test.go b/services/organisation_invite_service_test.go index f610120994..c9c18d92c3 100644 --- a/services/organisation_invite_service_test.go +++ b/services/organisation_invite_service_test.go @@ -1134,9 +1134,19 @@ func TestOrganisationInviteService_CancelOrganisationMemberInvite(t *testing.T) }, }, nil) - a.EXPECT().DeleteOrganisationInvite(gomock.Any(), gomock.Any()). + a.EXPECT().UpdateOrganisationInvite(gomock.Any(), gomock.Any()). Times(1).Return(nil) }, + want: &datastore.OrganisationInvite{ + OrganisationID: "123", + Status: datastore.InviteStatusCancelled, + InviteeEmail: "test@example.com", + Role: auth.Role{ + Type: auth.RoleAdmin, + Groups: []string{"ref"}, + Apps: nil, + }, + }, wantErr: false, }, } @@ -1151,7 +1161,7 @@ func TestOrganisationInviteService_CancelOrganisationMemberInvite(t *testing.T) tt.dbFn(ois) } - err := ois.CancelOrganisationMemberInvite(tt.args.ctx, tt.args.ivID) + iv, err := ois.CancelOrganisationMemberInvite(tt.args.ctx, tt.args.ivID) if tt.wantErr { require.NotNil(t, err) require.Equal(t, tt.wantErrCode, err.(*ServiceError).ErrCode()) @@ -1160,6 +1170,8 @@ func TestOrganisationInviteService_CancelOrganisationMemberInvite(t *testing.T) } require.Nil(t, err) + stripVariableFields(t, "organisation_invite", iv) + require.Equal(t, tt.want, iv) }) } } From 69fbac336ef59a4605f5a6241b76ebe7ddc9650b Mon Sep 17 00:00:00 2001 From: Dotun Jolaoso Date: Wed, 29 Jun 2022 12:05:20 +0100 Subject: [PATCH 3/8] fix: add support for jwt env variables (#813) --- config/config.go | 34 +++++++++++++++++++++++++++++----- convoy.env.example | 8 +++++++- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/config/config.go b/config/config.go index 8bc33a00ce..50c5ecb4cd 100644 --- a/config/config.go +++ b/config/config.go @@ -71,11 +71,11 @@ type NativeRealmOptions struct { } type JwtRealmOptions struct { - Enabled bool `json:"enabled"` - Secret string `json:"secret"` - Expiry int `json:"expiry"` - RefreshSecret string `json:"refresh_secret"` - RefreshExpiry int `json:"refresh_expiry"` + Enabled bool `json:"enabled" envconfig:"CONVOY_JWT_REALM_ENABLED"` + Secret string `json:"secret" envconfig:"CONVOY_JWT_SECRET"` + Expiry int `json:"expiry" envconfig:"CONVOY_JWT_EXPIRY"` + RefreshSecret string `json:"refresh_secret" envconfig:"CONVOY_JWT_REFRESH_SECRET"` + RefreshExpiry int `json:"refresh_expiry" envconfig:"CONVOY_JWT_REFRESH_EXPIRY"` } type SMTPConfiguration struct { @@ -421,6 +421,26 @@ func overrideConfigWithEnvVars(c *Configuration, override *Configuration) { c.Auth.File.Basic = override.Auth.File.Basic } + // CONVOY_JWT_SECRET + if !IsStringEmpty(override.Auth.Jwt.Secret) { + c.Auth.Jwt.Secret = override.Auth.Jwt.Secret + } + + // CONVOY_JWT_EXPIRY + if override.Auth.Jwt.Expiry != 0 { + c.Auth.Jwt.Expiry = override.Auth.Jwt.Expiry + } + + // CONVOY_JWT_REFRESH_SECRET + if !IsStringEmpty(override.Auth.Jwt.RefreshSecret) { + c.Auth.Jwt.RefreshSecret = override.Auth.Jwt.RefreshSecret + } + + // CONVOY_JWT_REFRESH_EXPIRY + if override.Auth.Jwt.RefreshExpiry != 0 { + c.Auth.Jwt.RefreshExpiry = override.Auth.Jwt.RefreshExpiry + } + // boolean values are weird; we have to check if they are actually set if _, ok := os.LookupEnv("CONVOY_MULTIPLE_TENANTS"); ok { @@ -438,6 +458,10 @@ func overrideConfigWithEnvVars(c *Configuration, override *Configuration) { if _, ok := os.LookupEnv("CONVOY_NATIVE_REALM_ENABLED"); ok { c.Auth.Native.Enabled = override.Auth.Native.Enabled } + + if _, ok := os.LookupEnv("CONVOY_JWT_REALM_ENABLED"); ok { + c.Auth.Jwt.Enabled = override.Auth.Jwt.Enabled + } } // LoadConfig is used to load the configuration from either the json config file diff --git a/convoy.env.example b/convoy.env.example index 3c5a31bd37..c20ab4cd7b 100644 --- a/convoy.env.example +++ b/convoy.env.example @@ -46,4 +46,10 @@ CONVOY_REQUIRE_AUTH=false CONVOY_BASIC_AUTH_CONFIG="[{\"username\": \"some-admin\",\"password\": \"some-password\",\"role\": {\"type\": \"super_user\",\"groups\": []}}]" CONVOY_API_KEY_CONFIG="[{\"api_key\":\"ABC1234\",\"role\":{\"type\":\"admin\",\"groups\":[\"group-uid-1\",\"group-uid-2\"],\"apps\":[\"apps-uid-1\",\"apps-uid-2\"]}}]" -CONVOY_NATIVE_REALM_ENABLED=true \ No newline at end of file +CONVOY_NATIVE_REALM_ENABLED=true + +CONVOY_JWT_REALM_ENABLED=true +CONVOY_JWT_SECRET= +CONVOY_JWT_EXPIRY= +CONVOY_JWT_REFRESH_SECRET= +CONVOY_JWT_REFRESH_EXPIRY= \ No newline at end of file From 4d1f6124dd81688fe923da3b8d1f21cb93b2d435 Mon Sep 17 00:00:00 2001 From: Subomi Oluwalana Date: Thu, 30 Jun 2022 08:46:41 +0100 Subject: [PATCH 4/8] Add: digitalocean script (#815) --- deploy/do-deploy | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 deploy/do-deploy diff --git a/deploy/do-deploy b/deploy/do-deploy new file mode 100755 index 0000000000..3c89cc4809 --- /dev/null +++ b/deploy/do-deploy @@ -0,0 +1,69 @@ +#!/bin/env bash + +set -e + +echo "Welcome to Convoy installer" +echo "" + +while true; do + echo "Should we setup a TLS certificate for you using Let's Encrypt?" + echo "Select no if you are using this internally and Convoy will not be reachable from the internet. y/n" + read -p "Answer: " yn + case $yn in + [Yy]* ) export USE_SELF_SIGNED_CERT=0; break ;; + [Nn]* ) export USE_SELF_SIGNED_CERT=1; break ;; + * ) echo "Please answer yes or no." ;; + esac +done + +read -p "Domain: " DOMAIN +export DOMAIN=$DOMAIN +echo "Ok we'll set up certs for https://$DOMAIN" +echo "" + +cd /etc/convoy/ + +# rewrite caddyfile +export TLS_BLOCK="" +if [[ $USE_SELF_SIGNED_CERT -eq 1 ]]; then + echo "Using a self signed certificate as requested" + export TLS_BLOCK="tls internal" +fi + +rm -f Caddyfile +envsubst > Caddyfile < convoy.json +echo "convoy.json ready" +echo "" +echo "" + +echo "Restarting services" + +# Drop Docker +docker-compose down + +# Start Docker +docker-compose up -d + +echo "" +echo "⌛️ Convoy looks up!" +echo "" +echo "🎉🎉🎉 Done! 🎉🎉🎉" +echo "" +echo "To stop the stack run 'docker-compose stop'" +echo "To start the stack again run 'docker-compose start'" From 6d08a3bd0e6116acc8c78424533ddaf2dde24ac4 Mon Sep 17 00:00:00 2001 From: Pelumi Muyiwa-Oni Date: Thu, 30 Jun 2022 11:30:22 +0100 Subject: [PATCH 5/8] Ui Bugfixes (#814) * refactored services * ui bugfixes * updated delete modal * ui bugfixes * updated create project form * updated forgot password --- .../add-analytics.component.html | 2 +- .../add-analytics/add-analytics.service.ts | 2 +- .../create-app/create-app.service.ts | 16 +- .../create-organisation.component.ts | 6 +- .../create-organisation.service.ts | 29 +- .../create-project-component.component.html | 291 +++++++++--------- .../create-project-component.component.ts | 31 +- .../create-project-component.service.ts | 48 +-- .../create-source/create-source.service.ts | 6 +- .../create-subscription.service.ts | 8 +- .../delete-modal/delete-modal.component.html | 4 +- .../delete-modal/delete-modal.component.ts | 1 + .../pages/account/account.component.ts | 13 +- .../private/pages/account/account.service.ts | 72 +++-- .../create-project.service.spec.ts | 16 - .../create-project/create-project.service.ts | 31 -- .../organisation/organisation.component.html | 18 +- .../organisation/organisation.component.ts | 20 +- .../pages/organisation/organisation.module.ts | 3 +- .../organisation/organisation.service.ts | 48 +-- .../app-details/app-details.component.html | 16 +- .../apps/app-details/app-details.component.ts | 8 +- .../apps/app-details/app-details.service.ts | 28 +- .../send-event/send-event.component.html | 94 +++--- .../send-event/send-event.component.ts | 20 +- .../pages/project/apps/apps.component.html | 2 +- .../event-delivery-details.service.ts | 8 +- .../pages/project/events/events.service.ts | 40 +-- .../project/settings/settings.component.html | 2 +- .../project/settings/settings.service.ts | 2 +- .../pages/project/sources/sources.service.ts | 2 +- .../subscriptions.component.html | 10 +- .../subscriptions/subscriptions.component.ts | 1 + .../subscriptions/subscriptions.service.ts | 4 +- .../pages/projects/projects.service.ts | 2 +- .../private/pages/teams/teams.component.html | 20 +- .../private/pages/teams/teams.component.ts | 4 +- .../app/private/pages/teams/teams.module.ts | 3 +- .../app/private/pages/teams/teams.service.ts | 138 +++++---- .../src/app/private/private.component.html | 4 +- .../src/app/private/private.component.ts | 26 +- .../src/app/private/private.service.ts | 60 ++-- .../accept-invite/accept-invite.service.ts | 46 +-- .../src/app/public/app/app.service.ts | 32 +- .../forgot-password.component.ts | 13 +- .../forgot-password.service.ts | 24 +- .../src/app/public/login/login.component.html | 2 +- .../src/app/public/login/login.component.ts | 6 +- .../src/app/public/login/login.service.ts | 24 +- .../reset-password.component.ts | 8 +- .../reset-password/reset-password.service.ts | 24 +- 51 files changed, 668 insertions(+), 670 deletions(-) delete mode 100644 web/ui/dashboard/src/app/private/pages/create-project/create-project.service.spec.ts delete mode 100644 web/ui/dashboard/src/app/private/pages/create-project/create-project.service.ts diff --git a/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.component.html b/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.component.html index b8a5a89e0f..75ac6c14bd 100644 --- a/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.component.html +++ b/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.component.html @@ -29,7 +29,7 @@
Would you like to enable analytics
- +
diff --git a/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.service.ts b/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.service.ts index e4ea847aa7..fe54de1898 100644 --- a/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.service.ts +++ b/web/ui/dashboard/src/app/private/components/add-analytics/add-analytics.service.ts @@ -18,7 +18,7 @@ export class AddAnalyticsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); diff --git a/web/ui/dashboard/src/app/private/components/create-app/create-app.service.ts b/web/ui/dashboard/src/app/private/components/create-app/create-app.service.ts index e3471154be..54d1d531e8 100644 --- a/web/ui/dashboard/src/app/private/components/create-app/create-app.service.ts +++ b/web/ui/dashboard/src/app/private/components/create-app/create-app.service.ts @@ -9,7 +9,7 @@ import { PrivateService } from '../../private.service'; export class CreateAppService { constructor(private http: HttpService, private privateService: PrivateService) {} - async updateApp(requestDetails: { appId: string; body: any }): Promise { + updateApp(requestDetails: { appId: string; body: any }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -19,13 +19,13 @@ export class CreateAppService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async createApp(requestDetails: { body: any }): Promise { + createApp(requestDetails: { body: any }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -35,13 +35,13 @@ export class CreateAppService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async addNewEndpoint(requestDetails: { appId: string; body: any }): Promise { + addNewEndpoint(requestDetails: { appId: string; body: any }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -51,13 +51,13 @@ export class CreateAppService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async getApp(appId: string): Promise { + getApp(appId: string): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -66,7 +66,7 @@ export class CreateAppService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); diff --git a/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.component.ts b/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.component.ts index 549822a222..d9a2990c09 100644 --- a/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.component.ts +++ b/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.component.ts @@ -32,10 +32,8 @@ export class CreateOrganisationComponent implements OnInit { this.loading = true; try { const response = await this.createOrganisationService.addOrganisation(this.addOrganisationForm.value); - if (response.status == true) { - this.generalService.showNotification({ style: 'success', message: response.message }); - this.closeModal.emit({ action: 'created' }); - } + this.generalService.showNotification({ style: 'success', message: response.message }); + this.closeModal.emit({ action: 'created' }); this.loading = false; } catch { this.loading = false; diff --git a/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.service.ts b/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.service.ts index 2b9b7f101f..fddd5c156b 100644 --- a/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.service.ts +++ b/web/ui/dashboard/src/app/private/components/create-organisation/create-organisation.service.ts @@ -3,22 +3,23 @@ import { HTTP_RESPONSE } from 'src/app/models/http.model'; import { HttpService } from 'src/app/services/http/http.service'; @Injectable({ - providedIn: 'root' + providedIn: 'root' }) export class CreateOrganisationService { + constructor(private http: HttpService) {} - constructor(private http:HttpService) { } - - async addOrganisation(requestDetails: { name: string }): Promise { - try { - const response = await this.http.request({ - url: `/organisations`, - method: 'post', - body: requestDetails - }); - return response; - } catch (error: any) { - return error; - } + addOrganisation(requestDetails: { name: string }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/organisations`, + method: 'post', + body: requestDetails + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } } diff --git a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.html b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.html index 2266c78488..f9aa7c8586 100644 --- a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.html +++ b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.html @@ -49,170 +49,173 @@

Project type

Please select a project type -
-

- Signature Details - This specifies your header and hash function for your project -

-
-
- - -
- input error icon - Enter header for project requests +
+
+

+ Signature Details + This specifies your header and hash function for your project +

+
+
+ + +
+ input error icon + Enter header for project requests +
-
-
- - -
- input error icon - Please select a hash +
+ + +
+ input error icon + Please select a hash +
-
-

- Retry Logic - - These are the specifications for the retry mechanism for your endpoints. In Linear time retry, event retries are done in linear time, while in Exponential back off retry, events are retried - progressively increasing the time before the next retry attempt. - -

-
-
- - -
- input error icon - Please select a retry logic mechanism +

+ Retry Logic + + These are the specifications for the retry mechanism for your endpoints. In Linear time retry, event retries are done in linear time, while in Exponential back off retry, events are + retried progressively increasing the time before the next retry attempt. + +

+
+
+ + +
+ input error icon + Please select a retry logic mechanism +
-
-
- - +
+ + -
- input error icon - Please enter your retry logic duration +
+ input error icon + Please enter your retry logic duration +
-
-
- - +
+ + -
- input error icon - Please enter a retry limit +
+ input error icon + Please enter a retry limit +
-
-

- Rate Limit Parameters - These are the specifications for how many events are to be sent to an endpoint per time -

-
-
- - -
- input error icon - Please enter your rate limit duration +

+ Rate Limit Parameters + These are the specifications for how many events are to be sent to an endpoint per time +

+
+
+ + +
+ input error icon + Please enter your rate limit duration +
-
-
- - -
- input error icon - Please enter a rate limit +
+ + +
+ input error icon + Please enter a rate limit +
-
-

Disable Failing Endpoints

-
-
- - -
+

Disable Failing Endpoints

+
+
+ + +
-
- - +
+ + +
+ +
+ +
diff --git a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.ts b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.ts index a2f77d045a..8aeeea2240 100644 --- a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.ts +++ b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.component.ts @@ -34,6 +34,7 @@ export class CreateProjectComponent implements OnInit { isCreatingProject = false; showApiKey = false; showSecretCopyText = false; + enableMoreConfig = false; apiKey!: string; hashAlgorithms = ['SHA256', 'SHA512', 'MD5', 'SHA1', 'SHA224', 'SHA384', 'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512', 'SHA512_256', 'SHA512_224']; retryLogicTypes = [ @@ -51,6 +52,7 @@ export class CreateProjectComponent implements OnInit { } async getProjectDetails() { + this.enableMoreConfig = true; try { const response = await this.privateService.getProjectDetails(); this.projectDetails = response.data; @@ -65,24 +67,21 @@ export class CreateProjectComponent implements OnInit { async createProject() { if (this.projectForm.invalid) return this.projectForm.markAllAsTouched(); - this.checkProjectConfig(); + + this.enableMoreConfig ? this.checkProjectConfig() : delete this.projectForm.value.config; + this.isCreatingProject = true; try { const response = await this.createProjectService.createProject(this.projectForm.value); this.isCreatingProject = false; - if (response.status === true) { - this.privateService.activeProjectDetails = response.data.group; - this.generalService.showNotification({ message: 'Project created successfully!', style: 'success' }); - this.apiKey = response.data.api_key.key; - this.projectDetails = response.data.group; - this.showApiKey = true; - } else { - this.generalService.showNotification({ message: response?.error?.message, style: 'error' }); - } - } catch (error: any) { + this.privateService.activeProjectDetails = response.data.group; + this.generalService.showNotification({ message: 'Project created successfully!', style: 'success' }); + this.apiKey = response.data.api_key.key; + this.projectDetails = response.data.group; + this.showApiKey = true; + } catch (error) { this.isCreatingProject = false; - this.generalService.showNotification({ message: error.message, style: 'error' }); } } @@ -92,12 +91,8 @@ export class CreateProjectComponent implements OnInit { this.isCreatingProject = true; try { const response = await this.createProjectService.updateProject(this.projectForm.value); - if (response.status === true) { - this.generalService.showNotification({ message: 'Project updated successfully!', style: 'success' }); - this.onAction.emit(response.data); - } else { - this.generalService.showNotification({ message: response?.error?.message, style: 'error' }); - } + this.generalService.showNotification({ message: 'Project updated successfully!', style: 'success' }); + this.onAction.emit(response.data); this.isCreatingProject = false; } catch (error) { this.isCreatingProject = false; diff --git a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.service.ts b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.service.ts index 090622096d..43fcc97e54 100644 --- a/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.service.ts +++ b/web/ui/dashboard/src/app/private/components/create-project-component/create-project-component.service.ts @@ -9,7 +9,7 @@ import { PrivateService } from '../../private.service'; export class CreateProjectComponentService { constructor(private http: HttpService, private privateService: PrivateService) {} - async createProject(requestDetails: { + createProject(requestDetails: { name: string; strategy: { duration: string; retry_count: string; type: string }; signature: { header: string; hash: string }; @@ -17,19 +17,21 @@ export class CreateProjectComponentService { rate_limit: number; rate_limit_duration: string; }): Promise { - try { - const response = await this.http.request({ - url: `${this.privateService.urlFactory('org')}/groups`, - body: requestDetails, - method: 'post' - }); - return response; - } catch (error: any) { - return error; - } + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `${this.privateService.urlFactory('org')}/groups`, + body: requestDetails, + method: 'post' + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } - async updateProject(requestDetails: { + updateProject(requestDetails: { name: string; strategy: { duration: string; retry_count: string; type: string }; signature: { header: string; hash: string }; @@ -37,15 +39,17 @@ export class CreateProjectComponentService { rate_limit: number; rate_limit_duration: string; }): Promise { - try { - const response = await this.http.request({ - url: `${this.privateService.urlFactory('org')}/groups/${this.privateService.activeProjectDetails.uid}`, - body: requestDetails, - method: 'put' - }); - return response; - } catch (error: any) { - return error; - } + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `${this.privateService.urlFactory('org')}/groups/${this.privateService.activeProjectDetails.uid}`, + body: requestDetails, + method: 'put' + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } } diff --git a/web/ui/dashboard/src/app/private/components/create-source/create-source.service.ts b/web/ui/dashboard/src/app/private/components/create-source/create-source.service.ts index 962eab2f87..13e58eaa41 100644 --- a/web/ui/dashboard/src/app/private/components/create-source/create-source.service.ts +++ b/web/ui/dashboard/src/app/private/components/create-source/create-source.service.ts @@ -20,7 +20,7 @@ export class CreateSourceService { }); return resolve(sourceResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); @@ -36,7 +36,7 @@ export class CreateSourceService { }); return resolve(projectResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); @@ -51,7 +51,7 @@ export class CreateSourceService { }); return resolve(projectResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); diff --git a/web/ui/dashboard/src/app/private/components/create-subscription/create-subscription.service.ts b/web/ui/dashboard/src/app/private/components/create-subscription/create-subscription.service.ts index db4bd9b977..ddd06831e6 100644 --- a/web/ui/dashboard/src/app/private/components/create-subscription/create-subscription.service.ts +++ b/web/ui/dashboard/src/app/private/components/create-subscription/create-subscription.service.ts @@ -20,7 +20,7 @@ export class CreateSubscriptionService { }); return resolve(projectResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); @@ -37,7 +37,7 @@ export class CreateSubscriptionService { }); return resolve(projectResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); @@ -53,7 +53,7 @@ export class CreateSubscriptionService { }); return resolve(projectResponse); - } catch (error: any) { + } catch (error) { return reject(error); } }); @@ -69,7 +69,7 @@ export class CreateSubscriptionService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); diff --git a/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.html b/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.html index 3eeb7eea75..268104ac7e 100644 --- a/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.html +++ b/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.html @@ -1,7 +1,7 @@ diff --git a/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.ts b/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.ts index 557b6ef450..7da2901c8c 100644 --- a/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.ts +++ b/web/ui/dashboard/src/app/private/components/delete-modal/delete-modal.component.ts @@ -10,6 +10,7 @@ export class DeleteModalComponent implements OnInit { @Output() deleteData = new EventEmitter(); @Input() isLoading: boolean = false; @Input() deleteText!: string; + @Input() deleteButtonText!: string; constructor() {} ngOnInit(): void {} diff --git a/web/ui/dashboard/src/app/private/pages/account/account.component.ts b/web/ui/dashboard/src/app/private/pages/account/account.component.ts index 5d986d235c..c4e9c3b519 100644 --- a/web/ui/dashboard/src/app/private/pages/account/account.component.ts +++ b/web/ui/dashboard/src/app/private/pages/account/account.component.ts @@ -88,10 +88,8 @@ export class AccountComponent implements OnInit { this.isUpdatingPassword = true; try { const response = await this.accountService.changePassword({ userId: this.userId, body: this.changePasswordForm.value }); - if (response.status === true) { - this.generalService.showNotification({ style: 'success', message: response.message }); - this.changePasswordForm.reset(); - } + this.generalService.showNotification({ style: 'success', message: response.message }); + this.changePasswordForm.reset(); this.isUpdatingPassword = false; } catch { this.isUpdatingPassword = false; @@ -101,10 +99,7 @@ export class AccountComponent implements OnInit { checkPassword(): boolean { const newPassword = this.changePasswordForm.value.password; const confirmPassword = this.changePasswordForm.value.password_confirmation; - if (newPassword === confirmPassword) { - return true; - } else { - return false; - } + if (newPassword === confirmPassword) return true; + return false; } } diff --git a/web/ui/dashboard/src/app/private/pages/account/account.service.ts b/web/ui/dashboard/src/app/private/pages/account/account.service.ts index 79819642fc..437e0e44d6 100644 --- a/web/ui/dashboard/src/app/private/pages/account/account.service.ts +++ b/web/ui/dashboard/src/app/private/pages/account/account.service.ts @@ -21,41 +21,47 @@ export class AccountService { } } - async getUserDetails(requestDetails: { userId: string }): Promise { - try { - const response = await this.http.request({ - url: `/users/${requestDetails.userId}/profile`, - method: 'get' - }); - return response; - } catch (error: any) { - return error; - } + getUserDetails(requestDetails: { userId: string }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/users/${requestDetails.userId}/profile`, + method: 'get' + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } - async editBasicInfo(requestDetails: { userId: string; body: { first_name: string; last_name: string; email: string } }): Promise { - try { - const response = await this.http.request({ - url: `/users/${requestDetails.userId}/profile`, - body: requestDetails.body, - method: 'put' - }); - return response; - } catch (error: any) { - return error; - } + editBasicInfo(requestDetails: { userId: string; body: { first_name: string; last_name: string; email: string } }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/users/${requestDetails.userId}/profile`, + body: requestDetails.body, + method: 'put' + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } - - async changePassword(requestDetails: { userId: string; body: { current_password: string; password: string; password_confirmation: string } }) { - try { - const response = await this.http.request({ - url: `/users/${requestDetails.userId}/password`, - body: requestDetails.body, - method: 'put' - }); - return response; - } catch (error: any) { - return error; - } + + changePassword(requestDetails: { userId: string; body: { current_password: string; password: string; password_confirmation: string } }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/users/${requestDetails.userId}/password`, + body: requestDetails.body, + method: 'put' + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } } diff --git a/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.spec.ts b/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.spec.ts deleted file mode 100644 index 5d9e0cb28a..0000000000 --- a/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { CreateProjectService } from './create-project.service'; - -describe('CreateProjectService', () => { - let service: CreateProjectService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(CreateProjectService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.ts b/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.ts deleted file mode 100644 index b9323dc509..0000000000 --- a/web/ui/dashboard/src/app/private/pages/create-project/create-project.service.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HTTP_RESPONSE } from 'src/app/models/http.model'; -import { HttpService } from 'src/app/services/http/http.service'; -import { PrivateService } from '../../private.service'; - -@Injectable({ - providedIn: 'root' -}) -export class CreateProjectService { - constructor(private http: HttpService, private privateService: PrivateService) {} - - async createProject(requestDetails: { - name: string; - strategy: { duration: string; retry_count: string; type: string }; - signature: { header: string; hash: string }; - disable_endpoint: boolean; - rate_limit: number; - rate_limit_duration: string; - }): Promise { - try { - const response = await this.http.request({ - url: `${this.privateService.urlFactory('org')}/groups`, - body: requestDetails, - method: 'post' - }); - return response; - } catch (error: any) { - return error; - } - } -} diff --git a/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.html b/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.html index f3287ee0b6..a298cf13a5 100644 --- a/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.html +++ b/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.html @@ -50,15 +50,11 @@

Danger zone

diff --git a/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.ts b/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.ts index 498c6cf2c0..8d1961b7e2 100644 --- a/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.ts +++ b/web/ui/dashboard/src/app/private/pages/organisation/organisation.component.ts @@ -46,11 +46,9 @@ export class OrganisationComponent implements OnInit { this.isEditingOrganisation = true; try { const response = await this.organisationService.updateOrganisation({ org_id: this.organisationId, body: this.editOrganisationForm.value }); - if (response.status == true) { - this.generalService.showNotification({ style: 'success', message: response.message }); - localStorage.setItem('CONVOY_ORG', JSON.stringify(response.data)); - window.location.reload(); - } + this.generalService.showNotification({ style: 'success', message: response.message }); + localStorage.setItem('CONVOY_ORG', JSON.stringify(response.data)); + window.location.reload(); this.isEditingOrganisation = false; } catch { this.isEditingOrganisation = false; @@ -73,13 +71,11 @@ export class OrganisationComponent implements OnInit { this.isDeletingOrganisation = true; try { const response = await this.organisationService.deleteOrganisation({ org_id: this.organisationId }); - if (response.status == true) { - this.generalService.showNotification({ style: 'success', message: response.message }); - localStorage.removeItem('CONVOY_ORG'); - this.router.navigateByUrl('/').then(() => { - window.location.reload(); - }); - } + this.generalService.showNotification({ style: 'success', message: response.message }); + localStorage.removeItem('CONVOY_ORG'); + this.router.navigateByUrl('/').then(() => { + window.location.reload(); + }); this.isDeletingOrganisation = false; } catch { this.isDeletingOrganisation = false; diff --git a/web/ui/dashboard/src/app/private/pages/organisation/organisation.module.ts b/web/ui/dashboard/src/app/private/pages/organisation/organisation.module.ts index a0f96c65ed..c0348de14e 100644 --- a/web/ui/dashboard/src/app/private/pages/organisation/organisation.module.ts +++ b/web/ui/dashboard/src/app/private/pages/organisation/organisation.module.ts @@ -3,11 +3,12 @@ import { CommonModule } from '@angular/common'; import { OrganisationComponent } from './organisation.component'; import { RouterModule, Routes } from '@angular/router'; import { ReactiveFormsModule } from '@angular/forms'; +import { DeleteModalModule } from '../../components/delete-modal/delete-modal.module'; const routes: Routes = [{ path: '', component: OrganisationComponent }]; @NgModule({ declarations: [OrganisationComponent], - imports: [CommonModule, ReactiveFormsModule, RouterModule.forChild(routes)] + imports: [CommonModule, ReactiveFormsModule, DeleteModalModule, RouterModule.forChild(routes)] }) export class OrganisationModule {} diff --git a/web/ui/dashboard/src/app/private/pages/organisation/organisation.service.ts b/web/ui/dashboard/src/app/private/pages/organisation/organisation.service.ts index 469df24810..bd24a1c48d 100644 --- a/web/ui/dashboard/src/app/private/pages/organisation/organisation.service.ts +++ b/web/ui/dashboard/src/app/private/pages/organisation/organisation.service.ts @@ -8,17 +8,19 @@ import { HttpService } from 'src/app/services/http/http.service'; export class OrganisationService { constructor(private http: HttpService) {} - async updateOrganisation(requestDetails: { org_id: string; body: { name: string } }): Promise { - try { - const response = await this.http.request({ - url: `/organisations/${requestDetails.org_id}`, - method: 'put', - body: requestDetails.body - }); - return response; - } catch (error: any) { - return error; - } + updateOrganisation(requestDetails: { org_id: string; body: { name: string } }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/organisations/${requestDetails.org_id}`, + method: 'put', + body: requestDetails.body + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } async logout(): Promise { @@ -34,16 +36,18 @@ export class OrganisationService { } } - async deleteOrganisation(requestDetails: { org_id: string }): Promise { - try { - const response = await this.http.request({ - url: `/organisations/${requestDetails.org_id}`, - method: 'delete', - body: null - }); - return response; - } catch (error: any) { - return error; - } + deleteOrganisation(requestDetails: { org_id: string }): Promise { + return new Promise(async (resolve, reject) => { + try { + const response = await this.http.request({ + url: `/organisations/${requestDetails.org_id}`, + method: 'delete', + body: null + }); + return resolve(response); + } catch (error) { + return reject(error); + } + }); } } diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.html b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.html index 69ba7bb1ae..3f50495347 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.html +++ b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.html @@ -77,7 +77,13 @@

Overview

-->
-
+

App Event Endpoints

@@ -176,7 +182,11 @@
{{ endpoint.description }}<

No endpoint has been added for selected app yet

-
+

App Portal

    @@ -277,5 +287,5 @@

    Endpoint Secret

diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.ts b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.ts index 7b12185ea9..33b9c5ebb6 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.ts +++ b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.component.ts @@ -44,6 +44,7 @@ export class AppDetailsComponent implements OnInit { ngOnInit() { this.isLoadingAppDetails = true; + if (this.privateService.activeProjectDetails?.type === 'outgoing') this.loadingAppPotalToken = true; this.checkScreenSize(); this.getAppDetails(this.route.snapshot.params.id); } @@ -52,7 +53,6 @@ export class AppDetailsComponent implements OnInit { this.location.back(); } - copyText(key: string) { const text = key; const el = document.createElement('textarea'); @@ -87,6 +87,8 @@ export class AppDetailsComponent implements OnInit { } async getAppPortalToken(requestDetail: { redirect: boolean }) { + if (this.privateService.activeProjectDetails?.type === 'incoming') return; + this.loadingAppPotalToken = true; try { @@ -123,9 +125,9 @@ export class AppDetailsComponent implements OnInit { this.screenWidth > 1010 ? (this.shouldRenderSmallSize = false) : (this.shouldRenderSmallSize = true); } - closeEditEndpointModal(){ + closeEditEndpointModal() { this.showAddEndpointModal = false; - this.selectedEndpoint = undefined + this.selectedEndpoint = undefined; } focusInput() { document.getElementById('tagInput')?.focus(); diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.service.ts b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.service.ts index a6832af367..862910a572 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.service.ts +++ b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/app-details.service.ts @@ -11,7 +11,7 @@ export class AppDetailsService { constructor(private http: HttpService, private privateService: PrivateService) {} - async getApps(): Promise { + getApps(): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -20,13 +20,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async getAppPortalToken(requestDetails: { appId: string }): Promise { + getAppPortalToken(requestDetails: { appId: string }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -36,13 +36,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async getApp(appId: string): Promise { + getApp(appId: string): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -51,13 +51,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async addNewEndpoint(requestDetails: { appId: string; body: any; token?: string }): Promise { + addNewEndpoint(requestDetails: { appId: string; body: any; token?: string }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -68,13 +68,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async editEndpoint(requestDetails: { appId: string; endpointId: string; body: any; token?: string }): Promise { + editEndpoint(requestDetails: { appId: string; endpointId: string; body: any; token?: string }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -85,13 +85,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async deleteEndpoint(requestDetails: { appId: string; endpointId: string }): Promise { + deleteEndpoint(requestDetails: { appId: string; endpointId: string }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -100,13 +100,13 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); } - async sendEvent(requestDetails: { body: any }): Promise { + sendEvent(requestDetails: { body: any }): Promise { return new Promise(async (resolve, reject) => { try { const response = await this.http.request({ @@ -116,7 +116,7 @@ export class AppDetailsService { }); return resolve(response); - } catch (error: any) { + } catch (error) { return reject(error); } }); diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.html b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.html index 58c1ff0f23..eedcf82cfc 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.html +++ b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.html @@ -1,55 +1,55 @@ \ No newline at end of file + + +
diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.ts b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.ts index 29a8ef6552..473140afe1 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.ts +++ b/web/ui/dashboard/src/app/private/pages/project/apps/app-details/send-event/send-event.component.ts @@ -45,16 +45,18 @@ export class SendEventComponent implements OnInit { }); return; } + + if (!this.convertStringToJson(this.sendEventForm.value.data)) return; + + this.sendEventForm.value.data = this.convertStringToJson(this.sendEventForm.value.data); this.isSendingNewEvent = true; try { const response = await this.appDetailsService.sendEvent({ body: this.sendEventForm.value }); - this.generalService.showNotification({ message: response.message, style: 'success' }); this.sendEventForm.reset(); this.onAction.emit({ action: 'sentEvent' }); this.isSendingNewEvent = false; - const projectId = this.appDetailsService.projectId; - this.router.navigate(['/projects/' + projectId + '/events'], { queryParams: { eventsApp: this.appId } }); + this.router.navigate(['/projects/' + this.appDetailsService.projectId + '/events'], { queryParams: { eventsApp: this.appId } }); } catch { this.isSendingNewEvent = false; } @@ -65,8 +67,18 @@ export class SendEventComponent implements OnInit { const appsResponse = await this.appDetailsService.getApps(); this.apps = appsResponse.data; - } catch (error: any) { + } catch (error) { return error; } } + + convertStringToJson(str: string) { + try { + const jsonObject = JSON.parse(str); + return jsonObject; + } catch { + this.generalService.showNotification({ message: 'Event data is not entered in correct JSON format', style: 'error' }); + return false; + } + } } diff --git a/web/ui/dashboard/src/app/private/pages/project/apps/apps.component.html b/web/ui/dashboard/src/app/private/pages/project/apps/apps.component.html index ac2aad55f5..df0ac472ee 100644 --- a/web/ui/dashboard/src/app/private/pages/project/apps/apps.component.html +++ b/web/ui/dashboard/src/app/private/pages/project/apps/apps.component.html @@ -168,7 +168,7 @@