From 05d802630e40314aa5352471559eb2e3db131794 Mon Sep 17 00:00:00 2001 From: optclblast Date: Sun, 26 May 2024 12:26:53 +0300 Subject: [PATCH] small fixes and docs update --- backend/README.md | 142 ++++++++++++++++++ .../rest/controllers/participants.go | 2 +- backend/internal/interface/rest/domain/dto.go | 19 +-- .../interface/rest/presenters/participants.go | 6 +- backend/internal/interface/rest/server.go | 7 - .../repository/organizations/repository.go | 17 ++- backend/migrations/blockd.sql | 7 +- 7 files changed, 168 insertions(+), 32 deletions(-) diff --git a/backend/README.md b/backend/README.md index 6ba00c5..25707aa 100644 --- a/backend/README.md +++ b/backend/README.md @@ -379,3 +379,145 @@ Response: ] } ``` +## POST **/organizations/{organization_id}/participants** +### Request body: +* name (string) +* position (string) +* wallet_address (string) + +### Example +Request: +``` bash +curl --request POST \ + --url http://localhost:8081/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants \ + --header 'Authorization: Bearer token' \ + --header 'content-type: application/json' \ + --data '{ + "name":"dodik", + "position":"employee", + "wallet_address":"0x8b1bc2590A3C9A1FEb349f1BacAfbc92CBC50156" +}' +``` + +Response: +``` json +{ + "_type": "participant", + "_links": { + "self": { + "href": "/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants/018fb42c-81dc-77f8-9eac-9d0540b34441" + } + }, + "id": "018fb42c-81dc-77f8-9eac-9d0540b34441", + "name": "dodik2", + "created_at": 1716714766812, + "updated_at": 1716714766812, + "is_user": false, + "is_admin": false, + "is_owner": false, + "is_active": false +} +``` +## GET **/organizations/{organization_id}/participants** +### Request body: +* ids (string array) + +### Example +Request: +``` bash +curl --request GET \ + --url http://localhost:8081/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants \ + --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTY3OTk5MjgzMzIsInVpZCI6IjAxOGZiNDE5LTliZjctN2QwOS05MzViLTNiOTAyNDc3ZDJkYiJ9.V_d3b8MvuOp01xDGX0g5Ab2nOvdyGL84WO01xPodTro' \ + --header 'content-type: application/json' \ + --data '{ + "ids":[ + "018fb419-9bf7-7d09-935b-3b902477d2db", + "018fb42c-1a60-7dd3-841a-fccce8575091", + "018fb42c-20b7-7c06-acb6-03b3ccb8b7e5" + ] +}' +``` + +Response: +``` json +{ + "_type": "participants", + "_links": { + "self": { + "href": "/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants" + } + }, + "participants": [ + { + "_type": "participant", + "_links": { + "self": { + "href": "/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants/018fb419-9bf7-7d09-935b-3b902477d2db" + } + }, + "id": "018fb419-9bf7-7d09-935b-3b902477d2db", + "name": "Bladee The Grand Drainer", + "credentials": { + "email": "bladeee@gmail.com", + "phone": "+79999999999", + "telegram": "@thebladee" + }, + "created_at": 1716724338478, + "updated_at": 1716724338478, + "is_user": true, + "is_admin": true, + "is_owner": true, + "is_active": true + }, + { + "_type": "participant", + "_links": { + "self": { + "href": "/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants/018fb42c-1a60-7dd3-841a-fccce8575091" + } + }, + "id": "018fb42c-1a60-7dd3-841a-fccce8575091", + "name": "New Employee", + "created_at": 1716725540320, + "updated_at": 1716725540320, + "is_user": false, + "is_admin": false, + "is_owner": false, + "is_active": false + }, + { + "_type": "participant", + "_links": { + "self": { + "href": "/organizations/018fb419-c3ad-7cda-81b8-cad30211b5fb/participants/018fb42c-20b7-7c06-acb6-03b3ccb8b7e5" + } + }, + "id": "018fb42c-20b7-7c06-acb6-03b3ccb8b7e5", + "name": "New Employee", + "created_at": 1716725541943, + "updated_at": 1716725541943, + "is_user": false, + "is_admin": false, + "is_owner": false, + "is_active": false + } + ] +} +``` +## POST **/organizations/{organization_id}/participants** +### Request body: +* title (string) +* owners (array of object { "public_key":"string" }) +* confirmations (int) + +### Example +Request: +``` bash + +``` + +Response: +``` json + +``` + diff --git a/backend/internal/interface/rest/controllers/participants.go b/backend/internal/interface/rest/controllers/participants.go index 0a44eb8..6b436a5 100644 --- a/backend/internal/interface/rest/controllers/participants.go +++ b/backend/internal/interface/rest/controllers/participants.go @@ -105,7 +105,7 @@ func (c *participantsController) New(w http.ResponseWriter, r *http.Request) ([] return nil, fmt.Errorf("error fetch organization id from context. %w", err) } - ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second) + ctx, cancel := context.WithTimeout(r.Context(), 3000*time.Second) defer cancel() participant, err := c.orgInteractor.AddParticipant(ctx, organizations.AddParticipantParams{ diff --git a/backend/internal/interface/rest/domain/dto.go b/backend/internal/interface/rest/domain/dto.go index 116197b..ae9e1a4 100644 --- a/backend/internal/interface/rest/domain/dto.go +++ b/backend/internal/interface/rest/domain/dto.go @@ -1,10 +1,5 @@ package domain -import ( - "encoding/json" - "fmt" -) - // Generic type Collection[T any] struct { @@ -97,8 +92,8 @@ type UpdateTransactionStatusRequest struct { type ListParticipantsRequest struct { IDs []string `json:"ids,omitempty"` - Cursor string `json:"cursor,omitempty"` - Limit uint8 `json:"limit,omitempty"` + Cursor string `json:"cursor,omitempty"` // not implemented + Limit uint8 `json:"limit,omitempty"` // not implemented } type AddEmployeeRequest struct { @@ -118,13 +113,3 @@ type NewMultisigRequest struct { type NewInviteLinkRequest struct { ExpirationDate int `json:"expiration_date"` } - -func BuildRequest[T any](data []byte) (*T, error) { - var req T - - if err := json.Unmarshal(data, &req); err != nil { - return nil, fmt.Errorf("error unmarshal request. %w", err) - } - - return &req, nil -} diff --git a/backend/internal/interface/rest/presenters/participants.go b/backend/internal/interface/rest/presenters/participants.go index d6550dd..1e75fff 100644 --- a/backend/internal/interface/rest/presenters/participants.go +++ b/backend/internal/interface/rest/presenters/participants.go @@ -53,11 +53,15 @@ func (p *participantsPresenter) responseParticipant( } } + domainParticipant.Position = user.Position() domainParticipant.IsUser = true domainParticipant.IsAdmin = user.IsAdmin() domainParticipant.IsOwner = user.IsOwner() domainParticipant.IsActive = user.Activated + } else if employee := participant.GetEmployee(); employee != nil { + domainParticipant.Name = employee.EmployeeName + domainParticipant.Position = employee.Position() } organizationID, err := ctxmeta.OrganizationId(ctx) @@ -67,7 +71,7 @@ func (p *participantsPresenter) responseParticipant( r := hal.NewResource( domainParticipant, - "/organizations/"+organizationID.String()+"/participants"+domainParticipant.ID, + "/organizations/"+organizationID.String()+"/participants/"+domainParticipant.ID, hal.WithType("participant"), ) diff --git a/backend/internal/interface/rest/server.go b/backend/internal/interface/rest/server.go index 3079e13..6f45a83 100644 --- a/backend/internal/interface/rest/server.go +++ b/backend/internal/interface/rest/server.go @@ -145,13 +145,6 @@ func (s *Server) buildRouter() { r.Route("/{participant_id}", func(r chi.Router) { r.Get("/", nil) - // r.Put("/", nil) // update user / employee - // r.Delete("/", nil) // remove user / employee - - // r.Route("/payroll", func(r chi.Router) { - // r.Put("/", nil) // edit - // r.Get("/", nil) - // }) }) }) }) diff --git a/backend/internal/usecase/repository/organizations/repository.go b/backend/internal/usecase/repository/organizations/repository.go index 781502c..020e17d 100644 --- a/backend/internal/usecase/repository/organizations/repository.go +++ b/backend/internal/usecase/repository/organizations/repository.go @@ -376,9 +376,16 @@ func (r *repositorySQL) Participants( PlaceholderFormat(sq.Dollar) if len(params.Ids) > 0 { - ouQuery = ouQuery.Where(sq.Eq{ - "ou.user_id": params.Ids, - }) + ouQuery = ouQuery.Where( + sq.Or{ + sq.Eq{ + "ou.user_id": params.Ids, + }, + sq.Eq{ + "ou.employee_id": params.Ids, + }, + }, + ) } rows, err := ouQuery.RunWith(r.Conn(ctx)).QueryContext(ctx) @@ -459,6 +466,7 @@ func (r *repositorySQL) Participants( query := sq.Select( "e.id", + "e.name", "e.user_id", "e.organization_id", "e.wallet_address", @@ -489,6 +497,7 @@ func (r *repositorySQL) Participants( for rows.Next() { var ( id uuid.UUID + name string userID uuid.UUID orgID uuid.UUID walletAddr []byte @@ -498,6 +507,7 @@ func (r *repositorySQL) Participants( if err = rows.Scan( &id, + &name, &userID, &orgID, &walletAddr, @@ -509,6 +519,7 @@ func (r *repositorySQL) Participants( employees = append(employees, &models.Employee{ ID: id, + EmployeeName: name, UserID: userID, OrganizationId: orgID, WalletAddress: walletAddr, diff --git a/backend/migrations/blockd.sql b/backend/migrations/blockd.sql index a6794fb..bd2518e 100644 --- a/backend/migrations/blockd.sql +++ b/backend/migrations/blockd.sql @@ -54,9 +54,10 @@ create index if not exists index_organizations_id create table employees ( id uuid primary key, + name varchar(250) default 'Employee', user_id uuid, organization_id uuid not null references organizations(id), - wallet_address text not null, + wallet_address bytea not null, created_at timestamp default current_timestamp, updated_at timestamp default current_timestamp ); @@ -69,7 +70,7 @@ create index if not exists index_user_id_organization_id create table organizations_users ( organization_id uuid not null references organizations(id), - user_id uuid not null references users(id), + user_id uuid default null, employee_id uuid default null, position varchar(300), added_at timestamp default current_timestamp, @@ -77,7 +78,7 @@ create table organizations_users ( deleted_at timestamp default null, is_admin bool default false, is_owner bool default false, - primary key(organization_id, user_id) + primary key(organization_id, user_id, employee_id) ); create index if not exists index_organizations_users_organization_id_user_id_is_admin