Skip to content

Commit 7a95e9f

Browse files
authored
Merge pull request #1 from singnet/development
Development
2 parents 123c39d + 40cb311 commit 7a95e9f

13 files changed

+143
-75
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
# snet-monitoring
1+
# Snet-Platform-Usage
2+
[![CircleCI](https://circleci.com/gh/singnet/snet-platform-usage.svg?style=svg)](https://circleci.com/gh/singnet/snet-platform-usage)

metering/constants.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ class StatusCode:
1010
"Access-Control-Allow-Origin": "*",
1111
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
1212
}
13-
PAYMENT_MODE_FREE_CALL = 'freecall'
1413

1514

1615
class StatusMessage:
1716
BAD_PARAMETER = "Request validation failed"
1817
SERVER_ERROR_MSG = "failed"
1918
SUCCESS_POST_CODE = "successful"
19+
20+
21+
PAYMENT_MODE_FREECALL_VALUE = "freecall"
22+
PAYMENT_MODE_ESCROW_VALUE = "escrow"

metering/handlers/freecall_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
setup_logger()
1212
logger = logging.getLogger(__name__)
1313

14-
required_keys = ['username', 'organization_id', 'service_id']
14+
required_keys = ['organization_id', 'service_id']
1515

1616

1717
def main(event, context):
1818
if validate_request(required_keys, event['queryStringParameters']):
1919
try:
2020
org_id = event['queryStringParameters']['organization_id']
2121
service_id = event['queryStringParameters']['service_id']
22-
username = event['requestContext']['authorizer']['claims']['email']
22+
username = event['queryStringParameters']['username']
2323
free_call_details = usage_service.get_free_call_details(
2424
username, org_id, service_id)
2525
return_value = make_response(

metering/handlers/usage_handler.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from constants import StatusCode, StatusMessage
55
from logger import setup_logger
66
from services import UsageService
7-
from utils import validate_request, make_response
7+
from utils import validate_request, make_response, usage_record_add_verify_fields
88

99
usage_service = UsageService()
1010

@@ -16,24 +16,26 @@
1616

1717

1818
def main(event, context):
19-
usage_detail_dict = json.loads(event['body'])
19+
request_dict = json.loads(event['body'])
2020

2121
try:
22-
if validate_request(required_keys, usage_detail_dict):
22+
if validate_request(required_keys, request_dict):
23+
usage_detail_dict = usage_record_add_verify_fields(request_dict)
24+
print(f"usage record after modification: {usage_detail_dict}")
2325
usage_service.save_usage_details(usage_detail_dict)
2426
response = make_response(
2527
StatusCode.SUCCESS_GET_CODE,
2628
json.dumps({"status": StatusMessage.SUCCESS_POST_CODE})
2729
)
2830
else:
29-
logger.error(f'Request validation failed {usage_detail_dict}')
31+
logger.error(f'Request validation failed {request_dict}')
3032
response = make_response(
3133
StatusCode.BAD_PARAMETERS_CODE,
3234
json.dumps({"status": StatusMessage.BAD_PARAMETER})
3335
)
3436
except Exception as e:
3537
logger.error(e)
36-
logger.error(f'failed for request {usage_detail_dict}')
38+
logger.error(f'failed for request {request_dict}')
3739
response = make_response(
3840
StatusCode.SERVER_ERROR_CODE,
3941
json.dumps({"status": StatusMessage.SERVER_ERROR_MSG})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from constants import StatusCode
2+
import json
3+
4+
from utils import make_response
5+
6+
7+
def main(event, context):
8+
return make_response(
9+
status_code=StatusCode.SUCCESS_GET_CODE,
10+
body=json.dumps({"data": "success"})
11+
)

metering/logger.py

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,11 @@
22

33

44
def setup_logger():
5-
logging.config.dictConfig({
6-
"version": 1,
7-
"disable_existing_loggers": False,
8-
"formatters": {
9-
"simple": {
10-
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
11-
}
12-
},
5+
logging.basicConfig(
6+
level=logging.INFO, format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S')
137

14-
"handlers": {
15-
"console": {
16-
"class": "logging.StreamHandler",
17-
"level": "DEBUG",
18-
"formatter": "simple",
19-
"stream": "ext://sys.stdout"
20-
}
218

22-
# "info_file_handler": {
23-
# "class": "logging.handlers.RotatingFileHandler",
24-
# "level": "INFO",
25-
# "formatter": "simple",
26-
# "filename": "info.log",
27-
# },
28-
#
29-
# "error_file_handler": {
30-
# "class": "logging.handlers.RotatingFileHandler",
31-
# "level": "ERROR",
32-
# "formatter": "simple",
33-
# "filename": "error.log",
34-
# "encoding": "utf8"
35-
# }
36-
},
37-
38-
"loggers": {
39-
"sqlalchemy": {
40-
"level": "ERROR",
41-
"handlers": ["console"],
42-
"propagate": "no"
43-
},
44-
"freecall_handler": {
45-
"level": "ERROR",
46-
"handlers": ["console"],
47-
"propagate": "no"
48-
},
49-
"": {
50-
"level": "ERROR",
51-
"handlers": ["console"],
52-
"propagate": "no"
53-
}
54-
},
55-
56-
"root": {
57-
"level": "ERROR",
58-
"handlers": ["console"]
59-
}
60-
})
9+
if __name__ == '__main__':
10+
setup_logger()
11+
logger = logging.getLogger()
12+
logger.info("hi, it is test")

metering/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
alembic==1.0.11
2+
boto3==1.9.216
23
Mako==1.1.0
34
MarkupSafe==1.1.1
45
PyMySQL==0.9.3

metering/serverless.yml

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,35 @@ package:
3636
- .gitignore
3737

3838
functions:
39+
verify-deamon:
40+
handler: handlers/verify_handler.main
41+
role: ${file(./config.${self:provider.stage}.json):ROLE}
42+
vpc:
43+
securityGroupIds:
44+
- ${file(./config.${self:provider.stage}.json):SG1}
45+
- ${file(./config.${self:provider.stage}.json):SG2}
46+
subnetIds:
47+
- ${file(./config.${self:provider.stage}.json):VPC1}
48+
- ${file(./config.${self:provider.stage}.json):VPC2}
49+
events:
50+
- http:
51+
path: /verify
52+
method: get
53+
authorizer:
54+
type: request
55+
arn: ${file(./config.${self:provider.stage}.json):SIGN_AUTHORIZER}
56+
identitySource: ${file(./config.${self:provider.stage}.json):SIGN_HEADERS}
57+
cors:
58+
origin: ${self:custom.origin.${self:provider.stage}}
59+
headers:
60+
- Content-Type
61+
- X-Amz-Date
62+
- Authorization
63+
- X-Api-Key
64+
- X-Amz-Security-Token
65+
- X-Amz-User-Agent
66+
- x-requested-with
67+
3968
get-freecalls:
4069
handler: handlers/freecall_handler.main
4170
role: ${file(./config.${self:provider.stage}.json):ROLE}
@@ -53,11 +82,10 @@ functions:
5382
- http:
5483
path: /usage/freecalls
5584
method: get
56-
# authorizer:
57-
# name: user-authorizer
58-
# type: COGNITO_USER_POOLS
59-
# arn: ${file(./config.${self:provider.stage}.json):AUTHORIZER}
60-
# identitySource: method.request.header.Authorization
85+
authorizer:
86+
type: request
87+
arn: ${file(./config.${self:provider.stage}.json):SIGN_AUTHORIZER}
88+
identitySource: ${file(./config.${self:provider.stage}.json):SIGN_HEADERS}
6189
cors:
6290
origin: ${self:custom.origin.${self:provider.stage}}
6391
headers:

metering/services.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
import json
12
import logging
23

4+
import boto3 as boto3
5+
6+
from settings import CONTRACT_API_ARN, CONTRACT_API_STAGE
37
from storage import DatabaseStorage
8+
from utils import is_free_call
49

510
logger = logging.getLogger(__name__)
611

@@ -25,5 +30,37 @@ def get_free_call_details(self, username, org_id, service_id, group_id=None):
2530

2631
def save_usage_details(self, usage_details_dict):
2732
# nedd to introduce entities when we enhance feature to this service right now directly using dicts
33+
if not is_free_call(usage_details_dict):
34+
channel_id = usage_details_dict['channel_id']
35+
group_id = usage_details_dict['group_id']
36+
user_address = APIUtilityService().get_user_address(group_id, channel_id)
37+
usage_details_dict['user_address'] = user_address
2838
self.storage_service.add_usage_data(usage_details_dict)
2939
return
40+
41+
42+
class APIUtilityService:
43+
44+
def __init__(self):
45+
self.lambda_client = boto3.client('lambda')
46+
47+
def get_user_address(self, group_id, channel_id):
48+
lambda_payload = {
49+
"httpMethod": "GET",
50+
"requestContext": {"stage": CONTRACT_API_STAGE},
51+
"path": f"/contract-api/group/{group_id}/channel/{channel_id}"
52+
}
53+
54+
try:
55+
response = self.lambda_client.invoke(
56+
FunctionName=CONTRACT_API_ARN,
57+
Payload=json.dumps(lambda_payload)
58+
)
59+
response_body_raw = json.loads(
60+
response.get('Payload').read())['body']
61+
response_body = json.loads(response_body_raw)
62+
user_address = response_body['data'][0]['sender']
63+
except Exception as e:
64+
print(e)
65+
raise Exception("Failed to get user address from marketplace")
66+
return user_address

metering/storage.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import logging
22

3-
from constants import PAYMENT_MODE_FREE_CALL
43
from models import UserOrgGroupModel, UsageModel
54
from repository.org_service_config_repository import OrgServiceRepo
65
from repository.usage_repository import UsageRepository
76
from repository.user_org_group_repository import UserOrgGroupRepository
7+
from constants import PAYMENT_MODE_FREECALL_VALUE, PAYMENT_MODE_ESCROW_VALUE
88

99
logger = logging.getLogger(__name__)
1010

@@ -29,14 +29,14 @@ def __init__(self):
2929

3030
def get_user_org_group_id(self, usage_details):
3131

32-
if usage_details['payment_mode'] == PAYMENT_MODE_FREE_CALL:
32+
if usage_details['payment_mode'] == PAYMENT_MODE_FREECALL_VALUE:
3333
user_org_group_id = self.user_org_group_repo.get_user_org_group_id_by_username(
3434
usage_details['username'],
3535
usage_details['organization_id'],
3636
usage_details['service_id'],
3737
usage_details['service_method']
3838
)
39-
elif usage_details['user_address'] is None:
39+
elif usage_details['payment_mode'] == PAYMENT_MODE_ESCROW_VALUE:
4040
user_org_group_id = self.user_org_group_repo.get_user_org_group_id_by_user_address(
4141
usage_details['user_address'],
4242
usage_details['organization_id'],
@@ -45,7 +45,7 @@ def get_user_org_group_id(self, usage_details):
4545
usage_details['group_id']
4646
)
4747
else:
48-
raise Exception('Unknown user request error')
48+
raise Exception("Invalid payment mode")
4949

5050
if user_org_group_id is not None:
5151
return user_org_group_id.id
@@ -101,7 +101,8 @@ def add_usage_data(self, usage_details):
101101
user_name=usage_details["username"],
102102
service_id=usage_details["service_id"],
103103
resource=usage_details["service_method"],
104-
request_id=usage_details["request_id"]
104+
request_id=usage_details["request_id"],
105+
payment_mode=usage_details["payment_mode"]
105106
)
106107
self.usage_repo.create_item(usage_record)
107108
logger.info(f"added usage data for {usage_details}")

0 commit comments

Comments
 (0)