Skip to content

Commit

Permalink
Merge pull request #196 from near-daos/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
vhorin-mp authored Mar 6, 2022
2 parents efb4d7a + e855438 commit cbf258e
Show file tree
Hide file tree
Showing 21 changed files with 917 additions and 51 deletions.
23 changes: 23 additions & 0 deletions apps/api/src/bounty/bounty.controller.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import {
BadRequestException,
Body,
Controller,
Get,
Param,
Patch,
Query,
UseFilters,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import {
ApiBadRequestResponse,
ApiForbiddenResponse,
ApiParam,
ApiQuery,
ApiResponse,
Expand All @@ -20,6 +24,7 @@ import {
HttpCacheInterceptor,
EntityQuery,
QueryFailedErrorFilter,
AccountAccessGuard,
} from '@sputnik-v2/common';
import {
BountyService,
Expand All @@ -32,6 +37,8 @@ import {

import { BountyCrudRequestInterceptor } from './interceptors/bounty-crud.interceptor';
import { BountyContextCrudRequestInterceptor } from './interceptors/bounty-context-crud.interceptor';
import { CouncilMemberGuard } from '../guards/council-member.guard';
import { UpdateBountyContextDto } from './dto/update-bounty-context.dto';

@ApiTags('Bounty')
@Controller()
Expand Down Expand Up @@ -104,4 +111,20 @@ export class BountyController {
): Promise<BountyContext[] | BountyContextResponse> {
return await this.bountyContextService.getMany(query, accountId);
}

@ApiResponse({
status: 200,
description: 'OK',
})
@ApiForbiddenResponse({
description:
'Account <accountId> identity is invalid - public key / bad signature/public key size / Invalid signature',
})
@UseGuards(AccountAccessGuard, CouncilMemberGuard)
@Patch('/bounty-contexts')
async updateBountyContexts(
@Body() body: UpdateBountyContextDto,
): Promise<void> {
await this.bountyContextService.updateMany(body);
}
}
2 changes: 2 additions & 0 deletions apps/api/src/bounty/bounty.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@sputnik-v2/bounty';
import { ProposalModule } from '@sputnik-v2/proposal';
import { CacheConfigService } from '@sputnik-v2/config/api-config';
import { DaoModule } from '@sputnik-v2/dao';

import { NearModule } from '../near/near.module';
import { BountyController } from './bounty.controller';
Expand All @@ -19,6 +20,7 @@ import { BountyController } from './bounty.controller';
useClass: CacheConfigService,
}),
TypeOrmModule.forFeature([Bounty, BountyClaim, BountyContext]),
DaoModule,
ProposalModule,
NearModule,
],
Expand Down
13 changes: 13 additions & 0 deletions apps/api/src/bounty/dto/update-bounty-context.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AccountBearer } from '@sputnik-v2/common';
import { ApiProperty } from '@nestjs/swagger';

export class UpdateBountyContextDto extends AccountBearer {
@ApiProperty()
daoId: string;

@ApiProperty()
ids: string[];

@ApiProperty()
isArchived: boolean;
}
10 changes: 7 additions & 3 deletions apps/api/src/guards/council-member.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ export class CouncilMemberGuard implements CanActivate {

async canActivate(context: ExecutionContext): Promise<boolean> {
const req = context.switchToHttp().getRequest();
const { daoId } = req.params;
const daoId = req.params.daoId || req.body.daoId;

const dao = await this.daoService.findById(daoId);

if (!dao) {
throw new NotFoundException(`DAO does not exist: ${daoId}`);
}

return req.isAuthenticated && dao.council.includes(req.accountId);
return (
req.isAuthenticated &&
(dao.council.length === 0
? dao.accountIds.includes(req.accountId)
: dao.council.includes(req.accountId))
);
}
}
18 changes: 18 additions & 0 deletions libs/bounty/src/bounty-context.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { ProposalService } from '@sputnik-v2/proposal';

import { BountyContextDto, BountyContextResponse } from './dto';
import { BountyContext } from './entities';
import { UpdateBountyContextDto } from '../../../apps/api/src/bounty/dto/update-bounty-context.dto';
import { UpdateResult } from 'typeorm/query-builder/result/UpdateResult';

@Injectable()
export class BountyContextService extends TypeOrmCrudService<BountyContext> {
Expand All @@ -28,6 +30,22 @@ export class BountyContextService extends TypeOrmCrudService<BountyContext> {
return this.bountyContextRepository.save(bountyContextDtos);
}

async updateMany({
daoId,
ids,
isArchived,
}: UpdateBountyContextDto): Promise<UpdateResult> {
return this.bountyContextRepository
.createQueryBuilder()
.update(BountyContext)
.where('daoId = :daoId', {
daoId,
})
.andWhere('id IN (:...ids) ', { ids })
.set({ isArchived })
.execute();
}

async getMany(
req: CrudRequest,
permissionsAccountId?: string,
Expand Down
12 changes: 10 additions & 2 deletions libs/transaction-handler/src/transaction-action-mapper.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { NearApiService, NearTransactionStatus } from '@sputnik-v2/near-api';
import { AccountChange } from '@sputnik-v2/near-indexer';
import { AccountChange, Transaction } from '@sputnik-v2/near-indexer';
import { sleep } from '@sputnik-v2/utils';

import {
Expand Down Expand Up @@ -50,7 +50,8 @@ export class TransactionActionMapperService {

if (
!originatedFromTransaction.transactionAction ||
!accountChange.causedByReceipt.receiptActions
!accountChange.causedByReceipt.receiptActions ||
this.isActFunctionCall(originatedFromTransaction)
) {
const txStatus = await this.getTxStatus(
originatedFromTransaction.transactionHash,
Expand Down Expand Up @@ -111,4 +112,11 @@ export class TransactionActionMapperService {
)
.flat();
}

private isActFunctionCall(transaction: Transaction): boolean {
return (
transaction.transactionAction?.args?.method_name === 'act_proposal' &&
transaction.transactionAction?.actionKind === 'FUNCTION_CALL'
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import api.app.astrodao.com.core.clients.HttpClient;
import api.app.astrodao.com.core.utils.JsonUtils;
import api.app.astrodao.com.openapi.models.CommentDeleteDto;
import api.app.astrodao.com.openapi.models.CommentDto;
import api.app.astrodao.com.openapi.models.CommentReportDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
Expand All @@ -12,6 +14,7 @@
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Map;

Expand Down Expand Up @@ -53,4 +56,41 @@ public ResponseEntity<String> createComment(String accountId, String publicKey,
HttpEntity<?> httpEntity = new HttpEntity<>(JsonUtils.writeValueAsString(commentDto), httpHeaders);
return httpClient.post(builder.toUriString(), httpEntity, String.class);
}

public ResponseEntity<String> reportComment(String accountId, String publicKey, String signature, BigDecimal commentId, String reason) {
HttpHeaders httpHeaders = httpClient.getBasicHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.ALL));

UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(apiUrl);
builder.pathSegment("comments", "report");

CommentReportDto commentDto = new CommentReportDto();
commentDto.setAccountId(accountId);
commentDto.setPublicKey(publicKey);
commentDto.setSignature(signature);
commentDto.setCommentId(commentId);
commentDto.setReason(reason);

HttpEntity<?> httpEntity = new HttpEntity<>(JsonUtils.writeValueAsString(commentDto), httpHeaders);
return httpClient.post(builder.toUriString(), httpEntity, String.class);
}

public ResponseEntity<String> deleteComment(String accountId, String publicKey, String signature, BigDecimal commentId, String reason) {
HttpHeaders httpHeaders = httpClient.getBasicHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Collections.singletonList(MediaType.ALL));

UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(apiUrl);
builder.pathSegment("comments", commentId.toString());

CommentDeleteDto commentDto = new CommentDeleteDto();
commentDto.setAccountId(accountId);
commentDto.setPublicKey(publicKey);
commentDto.setSignature(signature);
commentDto.setReason(reason);

HttpEntity<?> httpEntity = new HttpEntity<>(JsonUtils.writeValueAsString(commentDto), httpHeaders);
return httpClient.delete(builder.toUriString(), httpEntity, String.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package api.app.astrodao.com.core.controllers;

import api.app.astrodao.com.core.clients.HttpClient;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.Collections;
import java.util.Map;

@Component
@RequiredArgsConstructor
public class NotificationsApi {
protected final HttpClient httpClient;

@Value("${framework.api.url}")
private String apiUrl;

public ResponseEntity<String> getNotifications(Map<String, Object> queryParams) {
HttpHeaders httpHeaders = httpClient.getBasicHeaders();
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(apiUrl);
builder.pathSegment("notifications");
queryParams.forEach((key, value) -> builder.queryParam(key, value));

return httpClient.get(builder.toUriString(), new HttpEntity<>(httpHeaders), String.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package api.app.astrodao.com.core.dto.api.comments;

import api.app.astrodao.com.openapi.models.Comment;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = true)
public class CreatedComment extends Comment {
private String publicKey;
private String signature;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package api.app.astrodao.com.core.dto.api.notigications;

import api.app.astrodao.com.openapi.models.Dao;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;

import java.math.BigDecimal;
import java.time.OffsetDateTime;

@Data
public class Notification {
private Boolean isArchived;
private OffsetDateTime createdAt;
private OffsetDateTime updatedAt;
private String id;
private String daoId;
private Dao dao;
private String targetId;
private String signerId;
private JsonNode type;
private JsonNode status;
private JsonNode metadata;
private BigDecimal timestamp;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package api.app.astrodao.com.core.dto.api.notigications;

import lombok.Data;

import java.math.BigDecimal;
import java.util.List;

@Data
public class NotificationsResponse {
private BigDecimal count;
private BigDecimal total;
private BigDecimal page;
private BigDecimal pageCount;
private List<Notification> data;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package api.app.astrodao.com.core.dto.api.tokens;

import api.app.astrodao.com.openapi.models.AssetsNftEvent;

import java.util.ArrayList;

public class AssetsNftEventList extends ArrayList<AssetsNftEvent> {
}
7 changes: 6 additions & 1 deletion test-framework/src/main/resources/configs/framework.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ test:
# accountId: automation-01.testnet
dao: test-dao-1641395769436.sputnikv2.testnet
proposal: test-dao-1641395769436.sputnikv2.testnet-911
bounty: test-dao-1641395769436.sputnikv2.testnet-1578
aggregation.timeout: ${TEST_AGG_TIMEOUT:20}

framework:
Expand All @@ -13,4 +14,8 @@ accounts:
account1:
accountId: testdao2.testnet
publicKey: ed25519:8kqG6dyAheDqzoZh4hk9HbjBngG6fTnCD4zTw6sVud9K
signature: JJoq7fvBh6JXH9kVXtV0SoeT3YDSm9Gr6Ug4cmJNXAtuU2bZFu9/8bN26xw7MwYBRdWTZr2v81JZDO9zYaE8Dg==
signature: JJoq7fvBh6JXH9kVXtV0SoeT3YDSm9Gr6Ug4cmJNXAtuU2bZFu9/8bN26xw7MwYBRdWTZr2v81JZDO9zYaE8Dg==
account2:
accountId: automation-01.testnet
publicKey: ed25519:62vv9ViLDYnLtMZBUBgT8h5bB5yHLWYMbeeYKAVfChQF
signature: FLRzkKGeSdDUimtvkk4E7qMyViESPHxkMvBR1fTLKxfOCJqDWMYXciutO9O9nOJrXzp1d0u/aoR6kG4qwvHXCA==
Loading

0 comments on commit cbf258e

Please sign in to comment.