Skip to content

v1.0.6-alpha #116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7f9ba60
STR-297 :: get user on refresh (#97)
alcalawil Jan 25, 2023
df28fc5
adding platform DB stuff
Jan 25, 2023
7633c73
base64 encode nonce (#91)
alcalawil Jan 26, 2023
03424df
move admin api entities into admin api
Jan 26, 2023
9ae4940
deprecate old 'platform'
Jan 26, 2023
53d4dff
alter platform table instead of dropping it
Jan 26, 2023
4373877
change tabs to 2 spaces in migrations 5
Jan 27, 2023
1970863
Updated this_to_that naming convention in entities, repos
Jan 27, 2023
6f7e924
fixed some spacing, renamed many-to-many relationships as table-to-table
ocasta181 Jan 27, 2023
f63b69b
fix order, IF EXISTS, and missing commas
ocasta181 Jan 27, 2023
58e7788
fix race condition in docker
ocasta181 Jan 27, 2023
0b11424
fixed some things and broke some other things
Jan 27, 2023
4d8cef4
remove mocks since we're not using it anymore
ocasta181 Jan 27, 2023
c0f9bef
make goose happy
Jan 27, 2023
cb16928
rename to match many-to-many table names
ocasta181 Jan 27, 2023
e801cc3
Merge branch 'develop' into task/sean/str-385
Jan 27, 2023
f6fbc96
Update pkg/repository/platform.go
auroter Jan 27, 2023
64571d1
Update pkg/repository/platform.go
auroter Jan 27, 2023
5b9896f
Update pkg/service/platform.go
auroter Jan 27, 2023
a113ec3
Update pkg/service/platform.go
auroter Jan 27, 2023
36525e6
Merge pull request #100 from String-xyz/task/sean/str-385
auroter Jan 27, 2023
634558d
delete docker compose (we moved it to infra/local) and update readme …
Jan 27, 2023
0d85205
fix air install
Jan 28, 2023
c55bf9d
update migrations, env
Jan 30, 2023
a8a4f49
Merge pull request #102 from String-xyz/task/sean/docker-readme
auroter Jan 30, 2023
d59d202
fixed typo
saito-sv Jan 31, 2023
fb60141
Merge pull request #103 from String-xyz/task/marlon/persist_alb
saito-sv Jan 31, 2023
1ce5015
STR-357 :: If fingerprint analytics fails, continue anyways (#99)
alcalawil Jan 31, 2023
164132b
add 'name' to platform_member and member_invite tables
Feb 2, 2023
d8e2111
moved comma
Feb 2, 2023
5eebdfb
Merge pull request #105 from String-xyz/task/sean/add-name-member-invite
auroter Feb 2, 2023
cdd132a
Get Unit21 Real Time Rules engine and Checkout approvals working (#104)
Feb 6, 2023
bf7749e
update invite table (#107)
Feb 6, 2023
ba94e03
fix member_invite deactivated at default (#108)
auroter Feb 7, 2023
d31cdd2
api description must default to null
ocasta181 Feb 8, 2023
2e5fe43
STR-429 (#109)
saito-sv Feb 9, 2023
4102def
Refactor Transaction Execute (#110)
Feb 12, 2023
12b1efb
Task/andrin/str 354 (#115)
Feb 13, 2023
3c7990b
rename to match style guide; get asset based on chain (#117)
Feb 13, 2023
04ee50d
Persist Checkout Capture Responses (#118)
Feb 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ JWT_SECRET_KEY=hskdhfjfkdhsgafgwterurorhfh
UNIT21_API_KEY=
UNIT21_ENV=sandbox2-api
UNIT21_ORG_NAME=string
UNIT21_RTR_URL=https://rtr.sandbox2.unit21.com/evaluate
TWILIO_ACCOUNT_SID=AC034879a536d54325687e48544403cb4d
TWILIO_AUTH_TOKEN=
TWILIO_SMS_SID=MG367a4f51ea6f67a28db4d126eefc734f
Expand All @@ -38,4 +39,5 @@ FINGERPRINT_API_URL=https://api.fpjs.io/
STRING_INTERNAL_ID=00000000-0000-0000-0000-000000000000
STRING_WALLET_ID=00000000-0000-0000-0000-000000000001
STRING_BANK_ID=00000000-0000-0000-0000-000000000002
STRING_PLACEHOLDER_PLATFORM_ID=00000000-0000-0000-0000-000000000003
STRING_PLACEHOLDER_PLATFORM_ID=00000000-0000-0000-0000-000000000003
SERVICE_NAME=string_api
58 changes: 58 additions & 0 deletions .github/workflows/dev-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: deploy to development
permissions:
id-token: write
contents: read
on:
push:
branches: [develop]
jobs:
deploy:
environment:
name: development
url: https://string-api.dev.string-api.xyz

name: build push and deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: setup go
uses: actions/setup-go@v3
with:
go-version-file: go.mod
cache: true
cache-dependency-path: go.sum
- name: install deps and build
## TODO: Move all building into the docker container
run: |
go mod download
GOOS=linux GOARCH=amd64 go build -o ./cmd/app/main ./cmd/app/main.go

- name: configure aws credentials
uses: aws-actions/[email protected]
with:
aws-region: us-west-2
role-to-assume: ${{ secrets.ASSUME_ROLE }}

- name: login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: tag and push to Amazon ECR
env:
ECR_REPO: ${{ secrets.AWS_ACCT }}.dkr.ecr.us-west-2.amazonaws.com
SERVICE: string-api
IMAGE_TAG: latest
run: |
docker build -t $ECR_REPO/$SERVICE:$IMAGE_TAG ./cmd/app/
docker push $ECR_REPO/$SERVICE:$IMAGE_TAG

- name: deploy
env:
CLUSTER: string-core
SERVICE: string-api
AWS_REGION: us-west-2
run: |
aws ecs --region $AWS_REGION update-service --cluster $CLUSTER --service $SERVICE --force-new-deployment

7 changes: 3 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ on:
pull_request:
branches:
- develop

name: run tests
jobs:
lint:
Expand All @@ -17,7 +16,7 @@ jobs:
cache: true
cache-dependency-path: go.sum
- name: Install golangci-lint
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.47.3
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.1
- name: Run golangci-lint
run: golangci-lint run --version --verbose --out-format=github-actions

Expand Down Expand Up @@ -56,5 +55,5 @@ jobs:
- name: Coveralls
uses: coverallsapp/[email protected]
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: coverage.lcov
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: coverage.lcov
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
### For Live Reloading: ###
1. install [Air|https://github.com/cosmtrek/air]: `go install github.com/cosmtrek/air@latest`
2. run `air`
3. if you get `zsh: command not found: air` you need to add to PATH: `PATH=$PATH:$(go env GOPATH)/bin`
### To run the APIS: ###
1. Ensure you have the infra repo where the docker compose file is now located
2. run `docker compose -f ../infra/local/docker-compose.yml up`
3. You can also run with the -d flag to keep the process in the background, ie `docker compose -f -d ../infra/local/docker-compose.yml up`

### For migrations: ###
1. install [Goose|https://pressly.github.io/] `brew install goose`
2. Note, this binary is separate from the go package.
3. `goose postgres "host=localhost dbname=string_db user=string_db password=string_password sslmode=disable" down-to 0`
### To get a live terminal output from any repository being run by the infra docker compose: ###
1. Run `docker logs [docker container name] -f`
2. ie `docker logs platform-admin-api -f`
3. You can get the container names using `docker ps`
4. If you don't want the output in real time, you can omit the `-f` flag

### Postgres & Redis - Docker Compose: ***local dev only*** ###
1. To build and start the docker containers for the first time: `docker-compose up --build`
2. To shutdown the docker containers press `ctl + c`
### For migrations: ###
1. This is now handled by the docker compose file

### Docker Issues?
1. If docker is giving you an error when you try to `docker-compose up --build` try the following commands in order:
Expand All @@ -25,8 +25,10 @@ run `go install` to get dependencies installed

### For local testing: ###
run `go test`
or if you want to run a specific test, use `go test -run [TestName] [./path/to/dir] -v -count 1`
ie `go test -run TestGetSwapPayload ./pkg/service -v -count 1`

### Unit21: ###
This is a 3rd party service that offers the ability to evaluate risk at a transaction level and identify fraud. A client file exists to connect to their API. Documentation is here: https://docs.unit21.ai/reference/entities-api
You can create a test API key on the Unit21 dashboard. You will need to be setup as an Admin. Here are the instructions: https://docs.unit21.ai/reference/generate-api-keys
When setting up the production env variables, their URL will be: https://api.unit21.com/v1
When setting up the production env variables, their URL will be: https://api.unit21.com/v1
2 changes: 1 addition & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func loginRoute(services service.Services, e *echo.Echo) {
}

func verificationRoute(services service.Services, e *echo.Echo) {
handler := handler.NewVerification(e, services.Verification)
handler := handler.NewVerification(e, services.Verification, services.Device)
handler.RegisterRoutes(e.Group("/verification"))
}

Expand Down
31 changes: 18 additions & 13 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import (
func NewRepos(config APIConfig) repository.Repositories {
// TODO: Make sure all of the repos are initialized here
return repository.Repositories{
Auth: repository.NewAuth(config.Redis, config.DB),
User: repository.NewUser(config.DB),
Contact: repository.NewContact(config.DB),
Instrument: repository.NewInstrument(config.DB),
Device: repository.NewDevice(config.DB),
UserPlatform: repository.NewUserPlatform(config.DB),
Asset: repository.NewAsset(config.DB),
Network: repository.NewNetwork(config.DB),
Platform: repository.NewPlatform(config.DB),
Transaction: repository.NewTransaction(config.DB),
TxLeg: repository.NewTxLeg(config.DB),
Location: repository.NewLocation(config.DB),
Auth: repository.NewAuth(config.Redis, config.DB),
User: repository.NewUser(config.DB),
Contact: repository.NewContact(config.DB),
Instrument: repository.NewInstrument(config.DB),
Device: repository.NewDevice(config.DB),
UserToPlatform: repository.NewUserToPlatform(config.DB),
Asset: repository.NewAsset(config.DB),
Network: repository.NewNetwork(config.DB),
Platform: repository.NewPlatform(config.DB),
Transaction: repository.NewTransaction(config.DB),
TxLeg: repository.NewTxLeg(config.DB),
Location: repository.NewLocation(config.DB),
}
}

Expand All @@ -38,7 +38,11 @@ func NewServices(config APIConfig, repos repository.Repositories) service.Servic
verificationRepos := repository.Repositories{Contact: repos.Contact, User: repos.User, Device: repos.Device}
verification := service.NewVerification(verificationRepos)

auth := service.NewAuth(repos, fingerprint, verification)
// device service
deviceRepos := repository.Repositories{Device: repos.Device}
device := service.NewDevice(deviceRepos, fingerprint)

auth := service.NewAuth(repos, verification, device)
apiKey := service.NewAPIKeyStrategy(repos.Auth)
cost := service.NewCost(config.Redis)
executor := service.NewExecutor()
Expand All @@ -61,5 +65,6 @@ func NewServices(config APIConfig, repos repository.Repositories) service.Servic
Transaction: transaction,
User: user,
Verification: verification,
Device: device,
}
}
14 changes: 14 additions & 0 deletions api/handler/http_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,17 @@ func Conflict(c echo.Context, message ...string) error {
}
return c.JSON(http.StatusConflict, JSONError{Message: "Conflict", Code: "CONFLICT"})
}

func LinkExpired(c echo.Context, message ...string) error {
if len(message) > 0 {
return c.JSON(http.StatusForbidden, JSONError{Message: strings.Join(message, " "), Code: "LINK_EXPIRED"})
}
return c.JSON(http.StatusForbidden, JSONError{Message: "Forbidden", Code: "LINK_EXPIRED"})
}

func InvalidEmail(c echo.Context, message ...string) error {
if len(message) > 0 {
return c.JSON(http.StatusUnprocessableEntity, JSONError{Message: strings.Join(message, " "), Code: "INVALID_EMAIL"})
}
return c.JSON(http.StatusUnprocessableEntity, JSONError{Message: "Invalid email", Code: "INVALID_EMAIL"})
}
29 changes: 22 additions & 7 deletions api/handler/login.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handler

import (
b64 "encoding/base64"
"net/http"
"strings"

Expand Down Expand Up @@ -41,7 +42,8 @@ func (l login) NoncePayload(c echo.Context) error {
return InternalError(c)
}

return c.JSON(http.StatusOK, payload)
encodedNonce := b64.StdEncoding.EncodeToString([]byte(payload.Nonce))
return c.JSON(http.StatusOK, map[string]string{"nonce": encodedNonce})
}

func (l login) VerifySignature(c echo.Context) error {
Expand All @@ -56,11 +58,23 @@ func (l login) VerifySignature(c echo.Context) error {
return InvalidPayloadError(c, err)
}

resp, err := l.Service.VerifySignedPayload(body)
if err != nil && strings.Contains(err.Error(), "unknown device") {
return Unprocessable(c)
// base64 decode nonce
decodedNonce, _ := b64.URLEncoding.DecodeString(body.Nonce)
if err != nil {
LogStringError(c, err, "login: verify signature decode nonce")
return BadRequestError(c)
}
body.Nonce = string(decodedNonce)

resp, err := l.Service.VerifySignedPayload(body)
if err != nil {
if strings.Contains(err.Error(), "unknown device") {
return Unprocessable(c)
}
if strings.Contains(err.Error(), "invalid email") {
return InvalidEmail(c)
}

LogStringError(c, err, "login: verify signature")
return BadRequestError(c, "Invalid Payload")
}
Expand Down Expand Up @@ -93,7 +107,7 @@ func (l login) RefreshToken(c echo.Context) error {
return Unauthorized(c)
}

jwt, err := l.Service.RefreshToken(cookie.Value, body.WalletAddress)
resp, err := l.Service.RefreshToken(cookie.Value, body.WalletAddress)
if err != nil {
if strings.Contains(err.Error(), "wallet address not associated with this user") {
return BadRequestError(c, "wallet address not associated with this user")
Expand All @@ -102,14 +116,15 @@ func (l login) RefreshToken(c echo.Context) error {
LogStringError(c, err, "login: refresh token")
return BadRequestError(c, "Invalid or expired token")
}

// set auth in cookies
err = SetAuthCookies(c, jwt)
err = SetAuthCookies(c, resp.JWT)
if err != nil {
LogStringError(c, err, "RefreshToken: unable to set auth cookies")
return InternalError(c)
}

return c.JSON(http.StatusOK, jwt)
return c.JSON(http.StatusOK, resp)
}

// logout
Expand Down
7 changes: 7 additions & 0 deletions api/handler/transact.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handler

import (
"net/http"
"strings"

"github.com/String-xyz/string-api/pkg/model"
"github.com/String-xyz/string-api/pkg/service"
Expand Down Expand Up @@ -29,6 +30,7 @@ func (t transaction) Transact(c echo.Context) error {
LogStringError(c, err, "transact: execute bind")
return BadRequestError(c)
}

SanitizeChecksums(&body.CxAddr, &body.UserAddress)
// Sanitize Checksum for body.CxParams? It might look like this:
for i := range body.CxParams {
Expand All @@ -37,10 +39,15 @@ func (t transaction) Transact(c echo.Context) error {
userId := c.Get("userId").(string)
deviceId := c.Get("deviceId").(string)
res, err := t.Service.Execute(body, userId, deviceId)
if err != nil && (strings.Contains(err.Error(), "risk:") || strings.Contains(err.Error(), "payment:")) {
LogStringError(c, err, "transact: execute")
return Unprocessable(c)
}
if err != nil {
LogStringError(c, err, "transact: execute")
return InternalError(c)
}

return c.JSON(http.StatusOK, res)
}

Expand Down
13 changes: 13 additions & 0 deletions api/handler/user.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package handler

import (
b64 "encoding/base64"
"net/http"
"strings"

Expand Down Expand Up @@ -43,6 +44,14 @@ func (u user) Create(c echo.Context) error {
return InvalidPayloadError(c, err)
}

// base64 decode nonce
decodedNonce, _ := b64.URLEncoding.DecodeString(body.Nonce)
if err != nil {
LogStringError(c, err, "user: create user decode nonce")
return BadRequestError(c)
}
body.Nonce = string(decodedNonce)

resp, err := u.userService.Create(body)
if err != nil {
if strings.Contains(err.Error(), "wallet already associated with user") {
Expand Down Expand Up @@ -108,6 +117,10 @@ func (u user) VerifyEmail(c echo.Context) error {
return Conflict(c)
}

if strings.Contains(err.Error(), "link expired") {
return LinkExpired(c, "Link expired, please request a new one")
}

LogStringError(c, err, "user: email verification")
return InternalError(c, "Unable to send email verification")
}
Expand Down
11 changes: 6 additions & 5 deletions api/handler/verification.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ type Verification interface {
}

type verification struct {
service service.Verification
group *echo.Group
service service.Verification
deviceService service.Device
group *echo.Group
}

func NewVerification(route *echo.Echo, service service.Verification) Verification {
return &verification{service, nil}
func NewVerification(route *echo.Echo, service service.Verification, deviceService service.Device) Verification {
return &verification{service, deviceService, nil}
}

func (v verification) VerifyEmail(c echo.Context) error {
Expand All @@ -39,7 +40,7 @@ func (v verification) VerifyEmail(c echo.Context) error {

func (v verification) VerifyDevice(c echo.Context) error {
token := c.QueryParam("token")
err := v.service.VerifyDevice(token)
err := v.deviceService.VerifyDevice(token)
if err != nil {
LogStringError(c, err, "verification: device verification")
return BadRequestError(c)
Expand Down
3 changes: 1 addition & 2 deletions dev.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ ADD go.mod go.sum /string_api/
RUN go mod download

# install the air tool
RUN curl -fLo install.sh https://raw.githubusercontent.com/cosmtrek/air/master/install.sh \
&& chmod +x install.sh && sh install.sh && cp ./bin/air /bin/air
RUN go install github.com/cosmtrek/air@latest

# install goose for db migrations
RUN go install github.com/pressly/goose/v3/cmd/goose@latest
Expand Down
Loading