Compare commits
24 Commits
trunk
...
feat/kafka
| Author | SHA1 | Date |
|---|---|---|
|
|
3954a7a2c6 | |
|
|
865a8c670d | |
|
|
bf6e10a856 | |
|
|
ebe90899f0 | |
|
|
81f5921a40 | |
|
|
af796d16c8 | |
|
|
f576844b74 | |
|
|
67d76a30ca | |
|
|
bd31e9ec35 | |
|
|
eb4fe808d7 | |
|
|
4fcce1ccd9 | |
|
|
38563eb675 | |
|
|
7abc8666b9 | |
|
|
e945fc2f79 | |
|
|
7970ff99b0 | |
|
|
5221c50814 | |
|
|
c4cebcea6d | |
|
|
d09e5aaf53 | |
|
|
be6bae7dcf | |
|
|
fb95d41695 | |
|
|
d1c0369308 | |
|
|
fa8516b26f | |
|
|
a20b132280 | |
|
|
6cd624ced1 |
311
.drone.yml
311
.drone.yml
|
|
@ -1,296 +1,51 @@
|
|||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: Build & Push Images
|
||||
name: Build Images
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- trunk
|
||||
event:
|
||||
- push
|
||||
|
||||
steps:
|
||||
- name: Build & Publish Catalog
|
||||
image: git.vdhsn.com/barretthousen/drone-kaniko:v1.0.1
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /kaniko
|
||||
- name: Build & Publish
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.prod-backend"
|
||||
context: "./src"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-catalog
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
args:
|
||||
- "service=catalog"
|
||||
no-push: true
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
custom_labels:
|
||||
- com.barretthousen.service=catalog
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
# ---
|
||||
# kind: pipeline
|
||||
# type: kubernetes
|
||||
# name: Deploy beta
|
||||
|
||||
- name: Build & Publish Runner
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.prod-backend"
|
||||
context: "./src"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-runner
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=runner"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
custom_labels:
|
||||
- com.barretthousen.service=runner
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
# trigger:
|
||||
# event:
|
||||
# - push
|
||||
# branch:
|
||||
# - trunk
|
||||
|
||||
- name: Build & Publish Auth
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.prod-backend"
|
||||
context: "./src"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-auth
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=auth"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
custom_labels:
|
||||
- com.barretthousen.service=auth
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
|
||||
- name: Build & Publish Proxy Admin
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.prod-backend"
|
||||
context: "./src"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-proxy-admin
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=proxy-admin"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
custom_labels:
|
||||
- com.barretthousen.service=proxy-admin
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
depends_on:
|
||||
- Build & Publish Catalog
|
||||
- Build & Publish Runner
|
||||
- Build & Publish Auth
|
||||
|
||||
- name: Build & Publish Proxy Web
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.prod-backend"
|
||||
context: "./src"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-proxy-web
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=proxy-web"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
custom_labels:
|
||||
- com.barretthousen.service=proxy-web
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
depends_on:
|
||||
- Build & Publish Catalog
|
||||
- Build & Publish Runner
|
||||
- Build & Publish Auth
|
||||
|
||||
- name: Build & Publish Web Client
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.frontend"
|
||||
context: "./src/web-client"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/service-proxy-web
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=proxy-web"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
custom_labels:
|
||||
- com.barretthousen.service=proxy-web
|
||||
- com.barretthousen.version=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.git-ref=${DRONE_COMMIT_SHA}
|
||||
- com.barretthousen.build-date=${DRONE_BUILD_STARTED}
|
||||
- com.barrethousen.builder=${DRONE_COMMIT_AUTHOR}
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
depends_on:
|
||||
- Build & Publish Catalog
|
||||
- Build & Publish Runner
|
||||
- Build & Publish Auth
|
||||
- Build & Publish Proxy Admin
|
||||
- Build & Publish Proxy Web
|
||||
|
||||
- name: Build & Publish Admin Client
|
||||
image: plugins/kaniko
|
||||
settings:
|
||||
verbosity: debug
|
||||
dockerfile: "./src/Dockerfile.frontend"
|
||||
context: "./src/admin-client"
|
||||
target: production
|
||||
registry: git.vdhsn.com
|
||||
repo: git.vdhsn.com/barretthousen/client-admin-client
|
||||
enable_cache: true
|
||||
cache_repo: git.vdhsn.com/barretthousen/ci-cache
|
||||
snapshot_mode: redo
|
||||
skip_unused_stages: true
|
||||
build_args:
|
||||
- "service=admin-client"
|
||||
tags:
|
||||
- ${DRONE_COMMIT_SHA}
|
||||
- beta
|
||||
username:
|
||||
from_secret: DOCKER_USERNAME
|
||||
password:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
depends_on:
|
||||
- Build & Publish Catalog
|
||||
- Build & Publish Runner
|
||||
- Build & Publish Auth
|
||||
- Build & Publish Proxy Admin
|
||||
- Build & Publish Proxy Web
|
||||
|
||||
- name: Build Success Notify
|
||||
image: appleboy/drone-discord
|
||||
environment:
|
||||
DISCORD_WEBHOOK_ID:
|
||||
from_secret: DISCORD_WEBHOOK_ID
|
||||
DISCORD_WEBHOOK_TOKEN:
|
||||
from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
settings:
|
||||
username: Drone CI
|
||||
message: Barretthousen Image Builds Complete
|
||||
webhook_id:
|
||||
from_secret: DISCORD_WEBHOOK_ID
|
||||
webhook_token:
|
||||
from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
depends_on:
|
||||
- Build & Publish Catalog
|
||||
- Build & Publish Runner
|
||||
- Build & Publish Auth
|
||||
- Build & Publish Proxy Admin
|
||||
- Build & Publish Proxy Web
|
||||
- Build & Publish Web Client
|
||||
- Build & Publish Admin Client
|
||||
---
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: Promote Beta -> Prod
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- trunk
|
||||
event:
|
||||
- promote
|
||||
|
||||
steps:
|
||||
- name: Promote Services
|
||||
image: alpine
|
||||
environment:
|
||||
REGISTRY_NAME: "https://git.vdhsn.com"
|
||||
CONTENT_TYPE: "application/vnd.docker.distribution.manifest.v2+json"
|
||||
DOCKER_USERNAME:
|
||||
from_secret: DOCKER_USERNAME
|
||||
DOCKER_PASSWORD:
|
||||
from_secret: DOCKER_PASSWORD
|
||||
commands:
|
||||
- ./hack/promote.sh barretthousen/catalog beta prod
|
||||
|
||||
- name: Deploy Success
|
||||
image: appleboy/drone-discord
|
||||
environment:
|
||||
DISCORD_WEBHOOK_ID:
|
||||
from_secret: DISCORD_WEBHOOK_ID
|
||||
DISCORD_WEBHOOK_TOKEN:
|
||||
from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
settings:
|
||||
username: Drone CI
|
||||
message: Barretthousen Prod deployment success
|
||||
webhook_id:
|
||||
from_secret: DISCORD_WEBHOOK_ID
|
||||
webhook_token:
|
||||
from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
depends_on:
|
||||
- Promote Services
|
||||
|
||||
volumes:
|
||||
- name: cache
|
||||
temp:
|
||||
medium: memory
|
||||
# steps:
|
||||
# - name: discord notification
|
||||
# image: appleboy/drone-discord
|
||||
# environment:
|
||||
# DISCORD_WEBHOOK_ID:
|
||||
# from_secret: DISCORD_WEBHOOK_ID
|
||||
# DISCORD_WEBHOOK_TOKEN:
|
||||
# from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
# settings:
|
||||
# username: Drone CI
|
||||
# message: Weekly Server Update Complete!
|
||||
# webhook_id:
|
||||
# from_secret: DISCORD_WEBHOOK_ID
|
||||
# webhook_token:
|
||||
# from_secret: DISCORD_WEBHOOK_TOKEN
|
||||
|
|
|
|||
63
Makefile
63
Makefile
|
|
@ -8,11 +8,8 @@ GOBIN = $(shell go env GOPATH)/bin
|
|||
###################
|
||||
|
||||
.PHONY: setup
|
||||
setup: $(GOBIN)/sqlc $(GOBIN)/buf
|
||||
@awk '{ print $$1 }' .tool-versions | xargs -I {} asdf plugin add {} || true
|
||||
setup: $(GOBIN)/sqlc $(GOBIN)/buf ./env/.age.txt
|
||||
@asdf install || true
|
||||
@cd ./src/web-client && npm i
|
||||
@cd ./src/admin-client && npm i
|
||||
|
||||
.PHONY: gen
|
||||
gen: $(GOBIN)/sqlc buf.lock
|
||||
|
|
@ -29,63 +26,49 @@ clobber:
|
|||
KUBECONFIG=$(KUBECONFIG) ctlptl delete cluster kind-bh-local || true
|
||||
@rm -f $(KUBECONFIG)
|
||||
|
||||
.PHONY: secrets
|
||||
secrets: ./env/.age.txt
|
||||
|
||||
.PHONY: acceptance-test
|
||||
acceptance-test:
|
||||
@docker run -it --rm \
|
||||
-v $(PWD)/src/$(SERVICE)/acceptance-tests.yml:/tests/tests.yml \
|
||||
-e "TEST_HOST=$(ORIGIN)" \
|
||||
docker run -it --rm \
|
||||
-v $(pwd)/src/acceptance-tests.yml:/tests/tests.yml \
|
||||
-e "TEST_HOST=bh.localhost" \
|
||||
-e "TEST_ENV=local" \
|
||||
nytimes/httptest
|
||||
|
||||
|
||||
##############################
|
||||
# Container Image Building
|
||||
# see ./doc/deployment.md for details
|
||||
##############################
|
||||
|
||||
SERVICE = "catalog"
|
||||
ENV ?= ""
|
||||
ENV = ""
|
||||
ORIGIN = "https://barretthousen.com"
|
||||
BUILD_INITIATOR = "Development Machine"
|
||||
VERSION = $(shell git rev-parse --verify --short HEAD)
|
||||
GIT_REF = $(shell git rev-parse --verify HEAD)
|
||||
BUILD_DATE := $(shell date +%Y-%m-%d-%T)
|
||||
|
||||
.PHONY: build-tools-image
|
||||
build-tools-image:
|
||||
@docker build \
|
||||
--label 'com.barretthousen.version=$(VERSION)' \
|
||||
--label 'com.barretthousen.git-ref=$(GIT_REF)' \
|
||||
--label 'com.barretthousen.build-date=$(BUILD_DATE)' \
|
||||
--label 'com.barrethousen.builder=$(BUILD_INITIATOR)' \
|
||||
-t git.vdhsn.com/barretthousen/tools):$(VERSION) \
|
||||
-t git.vdhsn.com/barretthousen/tools):v1 \
|
||||
-f ./src/Dockerfile.tools ./src
|
||||
|
||||
@docker push git.vdhsn.com/barretthousen/tools:$(VERSION)
|
||||
@docker push git.vdhsn.com/barretthousen/tools:v1
|
||||
|
||||
.PHONY: build-client-image
|
||||
build-client-image:
|
||||
@docker build --target=production \
|
||||
docker build --target=production \
|
||||
--label 'com.barretthousen.service=$(SERVICE)' \
|
||||
--label 'com.barretthousen.version=$(VERSION)' \
|
||||
--label 'com.barretthousen.git-ref=$(GIT_REF)' \
|
||||
--label 'com.barretthousen.build-date=$(BUILD_DATE)' \
|
||||
--label 'com.barrethousen.builder=$(BUILD_INITIATOR)' \
|
||||
--build-arg 'service=$(SERVICE)' \
|
||||
--build-arg 'origin=$(ORIGIN)' \
|
||||
-t barretthousen/client-$(SERVICE):$(VERSION) \
|
||||
-t git.vdhsn.com/barretthousen/client-$(SERVICE):$(VERSION) \
|
||||
-f ./src/Dockerfile.frontend ./src/$(SERVICE)
|
||||
-f ./src/$(SERVICE)/Dockerfile.frontend ./src/$(SERVICE)
|
||||
|
||||
@docker push git.vdhsn.com/barretthousen/client-$(SERVICE):$(VERSION)
|
||||
@[ ! -z $(ENV) ] && docker tag git.vdhsn.com/barretthousen/client-$(SERVICE):$(VERSION) git.vdhsn.com/barretthousen/client-$(SERVICE):$(ENV) || true
|
||||
@[ ! -z $(ENV) ] && docker push git.vdhsn.com/barretthousen/client-$(SERVICE):$(VERSION) || true
|
||||
@[ ! -z $(ENV) ] && docker push git.vdhsn.com/barretthousen/client-$(SERVICE):$(ENV) || true
|
||||
|
||||
|
||||
.PHONY: build-backend-image
|
||||
build-backend-image:
|
||||
@docker build --target=production \
|
||||
docker build --target=production \
|
||||
--label 'com.barretthousen.service=$(SERVICE)' \
|
||||
--label 'com.barretthousen.version="$(VERSION)"' \
|
||||
--label 'com.barretthousen.git-ref="$(GIT_REF)"' \
|
||||
|
|
@ -94,29 +77,14 @@ build-backend-image:
|
|||
--build-arg 'service=$(SERVICE)' \
|
||||
-t barretthousen/service-$(SERVICE):$(VERSION) \
|
||||
-t git.vdhsn.com/barretthousen/service-$(SERVICE):$(VERSION) \
|
||||
-t git.vdhsn.com/barretthousen/service-$(SERVICE):$(ENV) \
|
||||
-f ./src/Dockerfile.prod-backend ./src
|
||||
|
||||
@docker push git.vdhsn.com/barretthousen/service-$(SERVICE):$(VERSION)
|
||||
|
||||
@[ ! -z $(ENV) ] && docker tag git.vdhsn.com/barretthousen/service-$(SERVICE):$(VERSION) git.vdhsn.com/barretthousen/service-$(SERVICE):$(ENV) || true
|
||||
@[ ! -z $(ENV) ] && docker push git.vdhsn.com/barretthousen/service-$(SERVICE):$(VERSION) || true
|
||||
@[ ! -z $(ENV) ] && docker push git.vdhsn.com/barretthousen/service-$(SERVICE):$(ENV) || true
|
||||
|
||||
# TODO: investigate tagging without needing to pull? https://dille.name/blog/2018/09/20/how-to-tag-docker-images-without-pulling-them/
|
||||
.PHONY: promote-client-prod
|
||||
promote-client-prod:
|
||||
@docker pull git.vdhsn.com/barretthousen/client-$(SERVICE):beta
|
||||
@docker tag git.vdhsn.com/barretthousen/client-$(SERVICE):beta git.vdhsn.com/barretthousen/client-$(SERVICE):prod
|
||||
@docker push git.vdhsn.com/barretthousen/client-$(SERVICE):prod
|
||||
|
||||
.PHONY: promote-backend-prod
|
||||
promote-backend-prod:
|
||||
@docker pull git.vdhsn.com/barretthousen/service-$(SERVICE):beta
|
||||
@docker tag git.vdhsn.com/barretthousen/service-$(SERVICE):beta git.vdhsn.com/barretthousen/service-$(SERVICE):prod
|
||||
@docker push git.vdhsn.com/barretthousen/service-$(SERVICE):prod
|
||||
|
||||
####################
|
||||
# File targets
|
||||
####################
|
||||
buf.lock: $(GOBIN)/buf
|
||||
@$(GOBIN)/buf mod update ./src
|
||||
|
||||
|
|
@ -138,4 +106,3 @@ age_identity=$(shell sops -d ./env/master.json)
|
|||
@echo "# public key: $(shell echo '$(age_identity)' | jq -r '.public_key')" >> $@
|
||||
@echo "$(shell echo '$(age_identity)' | jq -r '.private_key')" >> $@
|
||||
@echo "$@ created!"
|
||||
@echo "export SOPS_AGE_KEY_FILE=$(PWD)/env/.age.txt"
|
||||
|
|
|
|||
98
README.md
98
README.md
|
|
@ -1,105 +1,83 @@
|
|||
# [Barretthousen](https://barretthousen.com)
|
||||
|
||||
[](https://ci.vdhsn.com/Barretthousen/barretthousen)
|
||||
Search and get alerts for items across the most popular auction sites.
|
||||
|
||||
Built with microservice architecture and various fancy tools for learning purposes
|
||||
Built with microservice architecture, for learning purposes
|
||||
|
||||
### Links
|
||||
|
||||
- [Keybase Team Chat](keybase://team/barretthousen)
|
||||
- [Source](https://git.vdhsn.com/Barretthousen/barretthousen)
|
||||
- [Auction terms glossary](https://auctionsneapolitan.com/Auction-Terms-Glossary.html)
|
||||
- [User's Site](https://barretthousen.com)
|
||||
- [Admin Panel](https://admin.barretthousen.com)
|
||||
- [(Staging) User's Site](https://beta.barretthousen.com)
|
||||
- [(Staging) Admin Panel](https://beta.admin.barretthousen.com)
|
||||
|
||||
|
||||
### Goals
|
||||
|
||||
1. Ability to search upcoming and live auctions across major auction sites
|
||||
2. Get an email digest of upcoming auctions for the week
|
||||
|
||||
Future goals
|
||||
|
||||
1. Get email alerts when these auctions are about to go live
|
||||
2. Specify search criteria for email alerts
|
||||
|
||||
|
||||
## Technology
|
||||
|
||||
This project is for fun and learning so there are a lot of tools at play:
|
||||
For Users
|
||||
- [Prod](https://barretthousen.com)
|
||||
- [Staging](https://beta.barretthousen.com)
|
||||
|
||||
Infra
|
||||
- [Tilt](https://tilt.dev): local development env orchestration
|
||||
- [Ctlptl](https://github.com/tilt-dev/ctlptl): Automate local kubernetes clusters for local dev
|
||||
- [Docker]()
|
||||
- [Postgres]():
|
||||
- [Traefik]():
|
||||
- [Kustomize]():
|
||||
- [Helm]():
|
||||
For Admins
|
||||
|
||||
Backend
|
||||
- [Go]()
|
||||
- [goose](): Go SQL db migration tool
|
||||
- [Sqlc](https://sqlc.dev/): Generate Go code to query SQL databases from migrations in a type safe way
|
||||
- [Buf](): Nice frontend for protoc and .proto libraries
|
||||
- [Protobufs]():
|
||||
- [Prod](https://beta.barretthousen.com)
|
||||
- [Staging](https://admin.beta.barretthousen.com)
|
||||
- [Architecture Diagram (use diagrams.net)](./doc/Barretthousen_mvp.drawio)
|
||||
|
||||
Frontend
|
||||
- [Typescript]():
|
||||
- [SvelteKit](https://kit.svelte.dev/):
|
||||
- [TailwindCSS]():
|
||||
|
||||
|
||||
- [Diagram (use diagrams.net)](./doc/bh_design.drawio)
|
||||
|
||||

|
||||

|
||||
|
||||
### Services
|
||||
|
||||
> [Auction terms glossary](https://auctionsneapolitan.com/Auction-Terms-Glossary.html)
|
||||
|
||||
- [Web-client](./src/web-client/)
|
||||
- Web-client
|
||||
Frontend site that users access to browse upcoming auctions and subscribe for updates to their searches
|
||||
|
||||
- [Admin-client](./src/admin-client/)
|
||||
Enables site administrators to kicks off scrape and email jobs in Runner and Ringman, and view status on current/past jobs.
|
||||
|
||||
- [Catalog](./src/catalog/)
|
||||
- Catalog
|
||||
API for searching upcoming auctions.
|
||||
|
||||
- [Runner](./src/runner/)
|
||||
- Ringman
|
||||
Manages email subscriptions and sending emails to users about upcoming auctions.
|
||||
|
||||
- Runner
|
||||
Scrapes sites for upcoming auctions.
|
||||
Transforms the data into a suitable shape and stores it for use by the frontend.
|
||||
|
||||
- [Ringman](./src/ringman/)
|
||||
Manages email subscriptions and sending emails to users about upcoming auctions.
|
||||
- Auctioneer
|
||||
Enables site administrators to kicks off scrape and email jobs in Runner and Ringman, and view status on current/past jobs.
|
||||
|
||||
- [Proxy-web](./src/proxy-web/)
|
||||
Proxies JSON HTTP API requests for the web client to GRPC based services downstream
|
||||
|
||||
- [Proxy-admin](./src/proxy-admin/)
|
||||
Proxies JSON HTTP API requests for the admin client to GRPC based services downstream
|
||||
- BHDB
|
||||
Monolithic postgres datbabase tying it all together
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
You will need the following prereqs installed:
|
||||
- Docker
|
||||
- Make
|
||||
- [asdf](https://asdf-vm.com/guide/getting-started.html)
|
||||
### Contributing
|
||||
|
||||
|
||||
Everything you need is in the makefile:
|
||||
Install `asdf` and run `hack/asdf_plugin_setup`
|
||||
|
||||
```sh
|
||||
# install asdf tools, sqlc, buf
|
||||
# install asdf tools, build tooling, encryption key for sops
|
||||
make setup
|
||||
|
||||
# generate protobufs and sql boilerplate
|
||||
make gen
|
||||
|
||||
# spin up a k8s cluster, build and deploy services locally w/ hot reloading - be patient this takes a few minutes first run
|
||||
# spin up a k8s cluster, build and deploy services locally w/ hot reloading
|
||||
make dev
|
||||
|
||||
# build production docker images for the backend microservices, optionally push to the respective env
|
||||
make build-backend-image SERVICE=[catalog, runner, proxy-web, proxy-admin] [ENV=[beta, prod]]
|
||||
make build-backend-image SERVICE=[catalog, runner, proxy-client, proxy-admin] [ENV=[beta, prod]]
|
||||
|
||||
# build client docker image for web frontends, optionally push to the respective env
|
||||
make build-client-image SERVICE=[web-client, admin-client] [ENV=[beta, prod]]
|
||||
|
||||
# acceptance tests
|
||||
make acceptance-test SERVICE=[runner,catalog] ORIGIN=[beta.barretthousen.com,beta.admin.barretthousen.com]
|
||||
make build-client-image SERVICE=[web-client] [ENV=[beta, prod]]
|
||||
```
|
||||
|
||||
|
||||
For how to deploy [read me](./doc/deployment.md).
|
||||
|
|
|
|||
117
Tiltfile
117
Tiltfile
|
|
@ -7,11 +7,11 @@ print("""
|
|||
load('ext://helm_resource', 'helm_resource', 'helm_repo')
|
||||
load('ext://deployment', 'deployment_create')
|
||||
load('ext://restart_process', 'docker_build_with_restart')
|
||||
load('ext://uibutton', 'cmd_button', 'location', 'text_input')
|
||||
|
||||
helm_repo('bitnami', 'https://charts.bitnami.com/bitnami', labels=["9-repos"])
|
||||
helm_repo('traefik', 'https://traefik.github.io/charts', labels=["9-repos"])
|
||||
helm_repo('grafana', 'https://grafana.github.io/helm-charts', labels=["9-repos"])
|
||||
helm_repo('kafka-ui-github', 'https://provectus.github.io/kafka-ui', labels=["9-repos"])
|
||||
|
||||
helm_resource(
|
||||
'ingress',
|
||||
|
|
@ -52,16 +52,55 @@ helm_resource(
|
|||
labels=["9-data"]
|
||||
)
|
||||
|
||||
helm_resource(
|
||||
'kafka',
|
||||
'bitnami/kafka',
|
||||
namespace='barretthousen-local',
|
||||
flags=[
|
||||
'--set', 'numIoThreads=1',
|
||||
'--set', 'numNetworkThreads=1',
|
||||
],
|
||||
port_forwards=[port_forward(9092, 9092, name='kafka')],
|
||||
resource_deps=['bitnami'],
|
||||
labels=["9-data"]
|
||||
)
|
||||
|
||||
helm_resource(
|
||||
'kafka-ui',
|
||||
'kafka-ui-github/kafka-ui',
|
||||
namespace='barretthousen-local',
|
||||
flags=[
|
||||
'--set', 'envs.config.KAFKA_CLUSTERS_0_NAME=bh-kafka',
|
||||
'--set', 'envs.config.KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092'
|
||||
],
|
||||
port_forwards=[port_forward(9090, 8080, name='kafka-ui')],
|
||||
resource_deps=['kafka'],
|
||||
labels=["9-data"]
|
||||
)
|
||||
|
||||
def bh_client(service="", port_forwards=[], labels=['2-services'], deps=['ingress']):
|
||||
# docker_build('example-nodejs-image', '.',
|
||||
# build_args={'node_env': 'development'},
|
||||
# entrypoint='yarn run nodemon --ext js,mustache /app/index.js',
|
||||
# live_update=[
|
||||
# sync('.', '/app'),
|
||||
# run('cd /app && yarn install', trigger=['./package.json', './yarn.lock']),
|
||||
|
||||
# # if all that changed was start-time.txt, make sure the server
|
||||
# # reloads so that it will reflect the new startup time
|
||||
# run('touch /app/index.js', trigger='./start-time.txt'),
|
||||
|
||||
# # add a congrats message!
|
||||
# run('sed -i "s/Hello cats!/{}/g" /app/views/index.mustache'.
|
||||
# format(congrats)),
|
||||
# ])
|
||||
|
||||
basepath = './src/{}-client'.format(service)
|
||||
docker_build(
|
||||
ref='barretthousen/client-{}-client'.format(service),
|
||||
context=basepath,
|
||||
dockerfile='./src/Dockerfile.frontend'.format(service),
|
||||
dockerfile=basepath +'/Dockerfile.dev-frontend'.format(service),
|
||||
target='development',
|
||||
build_args={
|
||||
"service": '{}-client'.format(service)
|
||||
},
|
||||
entrypoint='vite dev --port=80 --host=0.0.0.0 --strictPort --logLevel info',
|
||||
live_update=[
|
||||
sync(basepath + '/src', '/opt/{}-client/src'.format(service)),
|
||||
|
|
@ -82,6 +121,7 @@ def bh_backend_service(service="", port_forwards=[], migrateDB=False, devMode=Tr
|
|||
'{}-go-compile'.format(service),
|
||||
'CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags "all=-N -l" -o .bin/{}-debug ./src/{}'.format(service, service),
|
||||
deps=['./src/{}'.format(service), './src/lib'],
|
||||
resource_deps=deps,
|
||||
labels=['3-compilation']
|
||||
)
|
||||
|
||||
|
|
@ -118,7 +158,7 @@ def bh_backend_service(service="", port_forwards=[], migrateDB=False, devMode=Tr
|
|||
'./src/runner',
|
||||
'./src/catalog',
|
||||
'./src/proxy-admin',
|
||||
'./src/proxy-web',
|
||||
'./src/proxy-client',
|
||||
'./src/lib'
|
||||
],
|
||||
live_update=[
|
||||
|
|
@ -145,56 +185,43 @@ k8s_resource(
|
|||
)
|
||||
|
||||
|
||||
bh_backend_service(service="auth", migrateDB=True, port_forwards=[
|
||||
port_forward(2345, name='Delve port')
|
||||
])
|
||||
|
||||
bh_backend_service(service="runner", migrateDB=True, port_forwards=[
|
||||
port_forward(2346, 2345, name='Delve port')
|
||||
])
|
||||
port_forward(2345, name='Delve port')
|
||||
], deps=["postgres", "kafka"])
|
||||
|
||||
bh_backend_service(service="catalog", migrateDB=True, port_forwards=[
|
||||
port_forward(2347, 2345, name='Delve port')
|
||||
])
|
||||
port_forward(2346, 2345, name='Delve port')
|
||||
], deps=["postgres", "kafka"])
|
||||
|
||||
bh_backend_service(service="proxy-admin", port_forwards=[
|
||||
port_forward(8082, 80, name="HTTP API @ localhost:8082")
|
||||
], deps=['ingress'])
|
||||
|
||||
bh_backend_service(service="proxy-web", port_forwards=[
|
||||
bh_backend_service(service="proxy-client", port_forwards=[
|
||||
port_forward(8081, 80, name="HTTP API @ localhost:8081")
|
||||
], deps=['ingress'])
|
||||
|
||||
bh_client(service='web', deps=["proxy-web-local"])
|
||||
bh_client(service='admin', deps=["proxy-admin-local"])
|
||||
|
||||
createAdminCmd = [
|
||||
'./hack/create_user.sh', 'admin@barretthousen.com', 'admin', 'ADMINISTRATOR'
|
||||
]
|
||||
|
||||
loginAdminCmd = [
|
||||
'curl', '-vvvv', '-X POST', '-H "Content-Type: application/json"',
|
||||
'-d "{\"email\":\"admin@barretthousen.com\", \"password\":\"admin\"}"',
|
||||
'http://bh.localhost:8000/api/v1/user'
|
||||
]
|
||||
|
||||
syncCatalogsCmd = [
|
||||
'curl', '-vvvv', '-X', 'PUT',
|
||||
'-H', 'Content-Type: application/json',
|
||||
'-H', 'bh-session-id: 2',
|
||||
'-d', '{\"targetSite\":\"All\"}',
|
||||
'http://admin.localhost:8000/api/v1/sync'
|
||||
]
|
||||
|
||||
local(createAdminCmd, quiet=False, echo_off=True)
|
||||
local(loginAdminCmd, quiet=False, echo_off=True)
|
||||
local(syncCatalogsCmd, quiet=False, echo_off=True)
|
||||
|
||||
cmd_button(
|
||||
name='Sync Catalogs',
|
||||
argv=syncCatalogsCmd,
|
||||
text='Sync Catalogs',
|
||||
location=location.NAV,
|
||||
icon_name='sync')
|
||||
bh_client(service='web')
|
||||
bh_client(service='admin')
|
||||
|
||||
|
||||
|
||||
# local_resource(
|
||||
# 'dev-web-client',
|
||||
# dir='./src/web-client',
|
||||
# cmd='npm i',
|
||||
# serve_dir='./src/web-client',
|
||||
# serve_cmd='npm run dev',
|
||||
# ignore=['./src/web-client/src'],
|
||||
# deps=[
|
||||
# './src/web-client/package.json',
|
||||
# './src/web-client/svelte.config.js',
|
||||
# './src/web-client/vite.config.ts'
|
||||
# ],
|
||||
# readiness_probe=probe(10, 2, 10, 1, 3, http_get=http_get_action(8080, 'localhost', 'http')),
|
||||
# links=[
|
||||
# link(url='http://localhost:8080', name='Web Client')
|
||||
# ],
|
||||
# labels=['2-services']
|
||||
# )
|
||||
|
|
|
|||
|
|
@ -0,0 +1,637 @@
|
|||
<mxfile host="app.diagrams.net" modified="2023-04-16T17:34:01.973Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0" etag="g01UfqVrYfXmJxj10a0k" version="21.1.7" type="device">
|
||||
<diagram name="High level" id="BL8KaFisCtBiJRqkGTb9">
|
||||
<mxGraphModel dx="3802" dy="1124" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-1" value="<div>Web Client</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry y="110" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-2" target="H4J2X_9uFRljxSkwpIMP-36">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-2" value="<div>Users</div>" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="-310" y="110" width="120" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=52.5;entryPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-3" target="JNN8aSlnDbWN0y9jmZyT-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-3" value="<div>Catalog</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="200" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-10" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1.013;exitY=0.613;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-1" target="JNN8aSlnDbWN0y9jmZyT-3">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="-80" y="130" as="sourcePoint" />
|
||||
<mxPoint y="150" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=52.5;entryPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-11" target="JNN8aSlnDbWN0y9jmZyT-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-11" value="<div>Ringman</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="150" y="90" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-12" value="" style="endArrow=classic;html=1;rounded=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.6;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-1" target="JNN8aSlnDbWN0y9jmZyT-11">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="-70" y="140" as="sourcePoint" />
|
||||
<mxPoint x="10" y="300" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-17" value="<div>BHDB</div>" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
||||
<mxGeometry x="470" y="110" width="60" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-19" target="JNN8aSlnDbWN0y9jmZyT-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-19" value="<div>Runner</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="290" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-20" value="<div>Runner</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="470" y="300" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-21" value="<div>Runner</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="480" y="310" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-22" value="<div>Runner</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="490" y="320" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-26" value="<div>Catalog</div>" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="-190" y="440" width="180" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-27" value="GetUpcoming(searchCriteria)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-26">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-1" value="<div>CreateUpcoming(Sale)</div>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-26">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-30" value="<div>Ringman</div>" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry y="440" width="180" height="180" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-31" value="Subscribe(email)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-30">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-3" value="VerifySubscription(email,token)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-30">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-32" value="<div>Unsubscribe(email)</div>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-30">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-33" value="<div>SendEmails()</div>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-30">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-34" value="GetJobs(searchCriteria)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-30">
|
||||
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-34" value="Runner" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="193" y="440" width="177" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-35" value="<div>FindNewUpcoming(criteria)<br></div>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-34">
|
||||
<mxGeometry y="30" width="177" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-1" value="GetJobs(searchCriteria)" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-34">
|
||||
<mxGeometry y="60" width="177" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-64" value="<div>Auction</div>" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="-190" y="680" width="180" height="300" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-65" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-66" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-65">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-67" value="ID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-65">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-68" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-69" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-68">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-70" value="Title" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-68">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-71" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-72" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-71">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-73" value="Description" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-71">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-74" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-75" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-74">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-76" value="<div>StartTS</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-74">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-121" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-122" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-121">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-123" value="<div>EndTS</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-121">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-118" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-119" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-118">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-120" value="<div>SourceSiteName</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-118">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-81" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-82" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-81">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-83" value="<div>SourceURL</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-81">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-84" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="240" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-85" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-84">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-86" value="Photo1" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-84">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-87" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-64">
|
||||
<mxGeometry y="270" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-88" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-87">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-89" value="Photo2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-87">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-93" value="<div>User</div>" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry y="680" width="180" height="150" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-94" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-93">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-95" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-94">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-96" value="ID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-94">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-146" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-93">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-147" value="UQ" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-146">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-148" value="EmailAddress" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-146">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-97" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-93">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-98" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-97">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-99" value="EmailVerifiedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-97">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-4" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-93">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-4">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-6" value="CreatedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-4">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-124" value="<div>ScrapeJob</div>" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="193" y="680" width="180" height="210" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-125" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-126" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-125">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-127" value="<div>ID</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-125">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-128" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;strokeColor=default;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-129" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-128">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-130" value="StartedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-128">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-131" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-132" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-131">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-133" value="CompletedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-131">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-134" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-135" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-134">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-136" value="AuctionsFound" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-134">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-137" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-138" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-137">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-139" value="TargetSiteName" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-137">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-149" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-124">
|
||||
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-150" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-149">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-151" value="Errors" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-149">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-156" value="EmailSubscription" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry y="840" width="180" height="150" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-157" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-156">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-158" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-157">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-159" value="ID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-157">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-178" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-156">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-179" value="UQ" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-178">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-180" value="UserID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-178">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-175" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-156">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-176" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-175">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-177" value="<div>SearchCriteria</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-175">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-166" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-156">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-167" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;strokeColor=inherit;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-166">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-168" value="<div>LastSentTS</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="JNN8aSlnDbWN0y9jmZyT-166">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="S1HCfoW5zDfGPMNCMrQO-7" target="JNN8aSlnDbWN0y9jmZyT-11">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="S1HCfoW5zDfGPMNCMrQO-7" target="JNN8aSlnDbWN0y9jmZyT-22">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="290" y="320" />
|
||||
<mxPoint x="290" y="360" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=52.5;entryPerimeter=0;" edge="1" parent="1" source="S1HCfoW5zDfGPMNCMrQO-7" target="JNN8aSlnDbWN0y9jmZyT-17">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="290" y="320" />
|
||||
<mxPoint x="290" y="163" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-7" value="<div>Auctioneer</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry y="280" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-11" value="Auctioneer" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="388" y="440" width="182" height="120" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-12" value="<div>TriggerSendEmails</div>" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-11">
|
||||
<mxGeometry y="30" width="182" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-39" value="TriggerFindNewUpcoming" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-11">
|
||||
<mxGeometry y="60" width="182" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-34" value="GetCommandHistory" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-11">
|
||||
<mxGeometry y="90" width="182" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-13" value="CommandHistory" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="388" y="680" width="180" height="240" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-14" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-15" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-14">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-16" value="<div>ID</div>" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-14">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-17" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-18" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-17">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-19" value="Name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-17">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-35" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-36" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-35">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-37" value="Initiator" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-35">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-20" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-21" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-20">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-22" value="ExecutedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-20">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-23" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-24" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-23">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-25" value="Target" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-23">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-26" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-27" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-26">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-28" value="Params" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-26">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-29" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-13">
|
||||
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-30" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-29">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-31" value="Errors" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="S1HCfoW5zDfGPMNCMrQO-29">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="S1HCfoW5zDfGPMNCMrQO-32" target="H4J2X_9uFRljxSkwpIMP-38">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-32" value="Admin" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="-310" y="280" width="120" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-3" value="SendEmailJob" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry y="1000" width="180" height="180" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-4" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-3">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-5" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-4">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-6" value="ID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-4">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-19" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-3">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-20" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-19">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-21" value="StartedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-19">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-22" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-3">
|
||||
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-23" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-22">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-24" value="CompletedTS" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-22">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-25" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-3">
|
||||
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-26" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-25">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-27" value="EmailsSent" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-25">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-28" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-3">
|
||||
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-29" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-28">
|
||||
<mxGeometry width="30" height="30" as="geometry">
|
||||
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-30" value="Errors" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=0;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-28">
|
||||
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-40" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="H4J2X_9uFRljxSkwpIMP-36" target="JNN8aSlnDbWN0y9jmZyT-1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-36" value="<div>@</div><div>alpha</div><div>beta<br></div>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.direct_data;whiteSpace=wrap;align=center;" vertex="1" parent="1">
|
||||
<mxGeometry x="-170" y="120" width="140" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="H4J2X_9uFRljxSkwpIMP-38" target="S1HCfoW5zDfGPMNCMrQO-7">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-38" value="<div>admin</div><div>alpha-admin</div><div>beta-admin<br></div>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.direct_data;whiteSpace=wrap;align=center;" vertex="1" parent="1">
|
||||
<mxGeometry x="-160" y="290" width="130" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-43" value="" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#00188D;shape=mxgraph.mscae.enterprise.lock" vertex="1" parent="1">
|
||||
<mxGeometry x="-119" y="240" width="39" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-44" value="" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#00188D;shape=mxgraph.mscae.enterprise.lock_unlocked" vertex="1" parent="1">
|
||||
<mxGeometry x="-119" y="70" width="37" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-51" value="Web Client" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="-380" y="440" width="180" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-52" value="SearchPage" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-51">
|
||||
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="H4J2X_9uFRljxSkwpIMP-53" value="SubscriptionsPage" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="H4J2X_9uFRljxSkwpIMP-51">
|
||||
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 183 KiB |
|
|
@ -1,177 +0,0 @@
|
|||
<mxfile host="app.diagrams.net" modified="2023-06-12T21:54:22.543Z" agent="Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/112.0" etag="x7K_nP_hUPP84gUb8Ro3" version="21.1.7" type="device">
|
||||
<diagram name="High level" id="BL8KaFisCtBiJRqkGTb9">
|
||||
<mxGraphModel dx="2053" dy="1131" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-1" value="<div>Web Client</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
|
||||
<mxGeometry x="-320" y="70" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-2" target="wSJkOsJQY9M_Z095WERL-4">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-2" value="<div>Users</div>" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="-840" y="110" width="120" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-17" value="<div>catalog-db</div>" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" parent="1" vertex="1">
|
||||
<mxGeometry x="80" y="57.5" width="80" height="105" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="JNN8aSlnDbWN0y9jmZyT-19" target="wSJkOsJQY9M_Z095WERL-50">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="JNN8aSlnDbWN0y9jmZyT-19" value="<div>Runner</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="1" vertex="1">
|
||||
<mxGeometry x="-60" y="440" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="S1HCfoW5zDfGPMNCMrQO-32" target="wSJkOsJQY9M_Z095WERL-8">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="S1HCfoW5zDfGPMNCMrQO-32" value="Admin" style="ellipse;shape=cloud;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||
<mxGeometry x="-830" y="400" width="120" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-4" target="JNN8aSlnDbWN0y9jmZyT-1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-21" value="<div>Path: /</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-19">
|
||||
<mxGeometry x="0.4522" y="-2" relative="1" as="geometry">
|
||||
<mxPoint x="1" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-4" target="wSJkOsJQY9M_Z095WERL-18">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-22" value="Path: /api" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-20">
|
||||
<mxGeometry x="0.3611" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-4" value="bh.com" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.direct_data;whiteSpace=wrap;align=center;" vertex="1" parent="1">
|
||||
<mxGeometry x="-640.5" y="120" width="160" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-5" value="" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#00188D;shape=mxgraph.mscae.enterprise.lock_unlocked" vertex="1" parent="1">
|
||||
<mxGeometry x="-579" y="70" width="37" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-23" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-8" target="wSJkOsJQY9M_Z095WERL-13">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-25" value="<div>Path:/</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-23">
|
||||
<mxGeometry x="0.43" y="-2" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-24" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-8" target="wSJkOsJQY9M_Z095WERL-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-26" value="Path:/api" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-24">
|
||||
<mxGeometry x="0.3263" y="-1" relative="1" as="geometry">
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-8" value="<div>admin.bh.com</div>" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.direct_data;whiteSpace=wrap;align=center;" vertex="1" parent="1">
|
||||
<mxGeometry x="-630.5" y="410" width="160.5" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-9" value="" style="sketch=0;aspect=fixed;pointerEvents=1;shadow=0;dashed=0;html=1;strokeColor=none;labelPosition=center;verticalLabelPosition=bottom;verticalAlign=top;align=center;fillColor=#00188D;shape=mxgraph.mscae.enterprise.lock" vertex="1" parent="1">
|
||||
<mxGeometry x="-570" y="360" width="39" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-13" value="Admin Client" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-320" y="350" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-17" target="JNN8aSlnDbWN0y9jmZyT-19">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-31" value="<div>/v1/sync</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-30">
|
||||
<mxGeometry x="0.2947" y="1" relative="1" as="geometry">
|
||||
<mxPoint y="-9" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-17" target="wSJkOsJQY9M_Z095WERL-42">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="-190" y="480" />
|
||||
<mxPoint x="-190" y="290" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-47" value="<div>/v1/notify</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-46">
|
||||
<mxGeometry x="-0.359" relative="1" as="geometry">
|
||||
<mxPoint x="70" y="-111" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-17" value="<div>Proxy Admin</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-320" y="440" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-18" target="wSJkOsJQY9M_Z095WERL-27">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="-190" y="200" />
|
||||
<mxPoint x="-190" y="110" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-29" value="<div>/v1/upcoming</div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-28">
|
||||
<mxGeometry x="-0.2889" y="-2" relative="1" as="geometry">
|
||||
<mxPoint x="58" y="-63" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-43" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-18" target="wSJkOsJQY9M_Z095WERL-42">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="-190" y="200" />
|
||||
<mxPoint x="-190" y="290" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-45" value="<div>/v1/register</div><div>/v1/verify</div><div>/v1/unsubscribe<br></div>" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-43">
|
||||
<mxGeometry x="0.3185" relative="1" as="geometry">
|
||||
<mxPoint x="32" y="-30" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-18" value="Proxy Web" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-320" y="160" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-27" target="JNN8aSlnDbWN0y9jmZyT-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-27" value="<div>Catalog</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-70" y="70" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-52" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-42" target="wSJkOsJQY9M_Z095WERL-49">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-42" value="<div>Ringman</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-60" y="250" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-49" value="ringman-db" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="237.5" width="80" height="105" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-50" value="runner-db" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="427.5" width="80" height="105" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-56" target="wSJkOsJQY9M_Z095WERL-17">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-58" value="curl /api/v1/sync" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="wSJkOsJQY9M_Z095WERL-57">
|
||||
<mxGeometry x="0.275" y="-2" relative="1" as="geometry">
|
||||
<mxPoint x="58" y="41" as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-56" value="<div>sync-cronjob</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-320" y="600" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-61" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="wSJkOsJQY9M_Z095WERL-59" target="wSJkOsJQY9M_Z095WERL-17">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="-120" y="560" />
|
||||
<mxPoint x="-280" y="560" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-59" value="<div>notify-cronjob</div>" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
|
||||
<mxGeometry x="-160" y="600" width="80" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wSJkOsJQY9M_Z095WERL-60" value="curl /api/v1/notify" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="1">
|
||||
<mxGeometry x="-70" y="580" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 36 KiB |
|
|
@ -5,10 +5,8 @@ Services deployed (using kustomize):
|
|||
- [catalog](./src/catalog)
|
||||
- [runner](./src/runner)
|
||||
- [proxy-admin](./src/proxy-admin)
|
||||
- [proxy-web](./src/proxy-web)
|
||||
|
||||
- [proxy-client](./src/proxy-client)
|
||||
- [web-client](./src/web-client)
|
||||
- [admin-client](./src/admin-client)
|
||||
|
||||
|
||||
Platform components deployed (using helm):
|
||||
|
|
@ -56,53 +54,35 @@ helm install --upgrade bh-db bitnami/postgresql -n 'barretthousen-beta' \
|
|||
|
||||
### Deployment steps
|
||||
|
||||
1. Build and publish images to `beta`
|
||||
1. Build and publish prod images
|
||||
```sh
|
||||
export ENV=beta; # if not specified, will only build and push for the git commit
|
||||
make build-backend-image SERVICE=catalog
|
||||
make build-backend-image SERVICE=runner
|
||||
make build-backend-image SERVICE=auth
|
||||
make build-backend-image SERVICE=proxy-admin
|
||||
make build-backend-image SERVICE=proxy-web
|
||||
make build-backend-image SERVICE=catalog env=beta
|
||||
make build-backend-image SERVICE=runner env=beta
|
||||
make build-backend-image SERVICE=proxy-admin env=beta
|
||||
make build-backend-image SERVICE=proxy-client env=beta
|
||||
|
||||
# for prod drop `beta prefix
|
||||
make build-client-image SERVICE=web-client
|
||||
make build-client-image SERVICE=admin-client
|
||||
make build-client-image SERVICE=web-client env=beta
|
||||
```
|
||||
|
||||
2. Rolling restart deployments in the beta env
|
||||
```sh
|
||||
# for prod drop `-beta` suffix
|
||||
kubectl rollout restart -n barretthousen-beta deployment runner-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment runner-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment catalog-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment catalog-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment auth-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment auth-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment proxy-admin-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment proxy-admin-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment proxy-web-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment proxy-web-beta -w
|
||||
kubectl rollout restart -n barretthousen-beta deployment proxy-client-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment proxy-client-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment web-client-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment web-client-beta -w
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment admin-client-beta
|
||||
kubectl rollout status -n barretthousen-beta deployment admin-client-beta -w
|
||||
```
|
||||
|
||||
3. Promote images to prod
|
||||
```sh
|
||||
make promote-backend-prod SERVICE=catalog
|
||||
make promote-backend-prod SERVICE=runner
|
||||
make promote-backend-prod SERVICE=auth
|
||||
make promote-backend-prod SERVICE=proxy-admin
|
||||
make promote-backend-prod SERVICE=proxy-web
|
||||
|
||||
make promote-client-prod SERVICE=web-client
|
||||
make promote-client-prod SERVICE=admin-client
|
||||
```
|
||||
## Prod
|
||||
|
||||
TBD
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ spec:
|
|||
stdin: true
|
||||
tty: true
|
||||
env:
|
||||
- name: BH_CLIENT_INTERNAL_API_HOST
|
||||
value: "http://proxy-admin"
|
||||
- name: ORIGIN
|
||||
value: https://admin.barretthousen.com
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: auth
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
service: auth
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: auth
|
||||
spec:
|
||||
serviceAccountName: barretthousen-service
|
||||
containers:
|
||||
- name: auth
|
||||
image: barretthousen/service-auth:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 5001
|
||||
name: grpc
|
||||
command:
|
||||
- /opt/auth
|
||||
args:
|
||||
- -migrate
|
||||
resources:
|
||||
limits:
|
||||
cpu: "250m"
|
||||
memory: "128Mi"
|
||||
volumeMounts:
|
||||
- mountPath: /config/
|
||||
name: auth-config
|
||||
volumes:
|
||||
- name: auth-config
|
||||
secret:
|
||||
secretName: auth-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: auth
|
||||
spec:
|
||||
selector:
|
||||
service: auth
|
||||
ports:
|
||||
- port: 5001
|
||||
targetPort: 5001
|
||||
name: grpc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: auth-config
|
||||
stringData:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 5001
|
||||
db_service:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
host: bh-db
|
||||
name: bh
|
||||
user: auth-service
|
||||
password: auth-service
|
||||
db_migrate:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
host: bh-db
|
||||
name: bh
|
||||
user: postgres
|
||||
password: bh-admin
|
||||
|
|
@ -46,7 +46,6 @@ spec:
|
|||
ports:
|
||||
- port: 5001
|
||||
targetPort: 5001
|
||||
name: grpc
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ spec:
|
|||
path: "/api"
|
||||
backend:
|
||||
service:
|
||||
name: proxy-web
|
||||
name: proxy-client
|
||||
port:
|
||||
number: 80
|
||||
- pathType: ImplementationSpecific
|
||||
|
|
|
|||
|
|
@ -4,24 +4,5 @@ metadata:
|
|||
name: bh-registry
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
stringData:
|
||||
.dockerconfigjson: ENC[AES256_GCM,data:bfqlh7Vy3HDYFtgv56xO+8lXOLO9bQWRC16N8hAzv6xJaIN6CmXDwFzoLoGWPrP9s/o446tuOEJEylf5z/ITnLtdGJgMsN13Xk7OiF9B2unV8yOOrzt6U6R2s5cFpbSL3tAHQmDKHxRrzbvyV2J3magen7oHQWbkwkOQq7FqV/k7wFly+bei1u+YLJ9hq798Xa5HG9j4LsVWi5izKt1BBss2xFlo3yzEFqNmQ+AzcUN1uK1xwStplK4IKC36rewONDS+yyqj830LLShb,iv:qDwYxBqK+ZamBcWEuF+UEfW8gLFROagaBqVAc1tCjUI=,tag:OYhChcvisxP0r3kQ4hq4SA==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
age:
|
||||
- recipient: age1d5vst0g82v6xml29ydsrxefmf3vclgm6dj3npw6mefa7yu9xueaqztjqlg
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaRG1ERkdkTXMvUllCSHdS
|
||||
TXVBVWNMd0hYeXMvTXh6OFVTYXV0MkVoOEJ3Ck9XakJTbHMyTWpvazFzYUtNcmtx
|
||||
NTVoVnUwWkpKYjg4MWs1dmxpT3JGRFUKLS0tIHdHRk8yL1lCRk9DM0haYjN4Z1Ry
|
||||
d25rRklvOUdLQlU0S2l0WXBpUXhyR2MKQgJXQgxp0T2rr0V2NjwSjWFlzNyig5vW
|
||||
S8PW6OpCOyfMqzz5NWTdUVymY7UEdAguwZH+MY2DdvEn3NM/TcnRwA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2023-05-27T02:48:45Z"
|
||||
mac: ENC[AES256_GCM,data:SCjcJPn7hg9sUFYlOUKAVJBXKNIrcz/x3aqyX43xf7UO7Zo/pGDp1JDaKA7lCaKTgPEAe1zRRv6LjejNGX3DlpmxMS6o2xaI3nb0e0CnLj9t9t57L5svrciwh9wOennWj26DirgzAB+uqCJ/NGOJh4S8yTPOF5MgBNkqNw6FN94=,iv:YTtckdYzKnBBqbQYvjw9FpvGHsUxX6MnAeNopYhFe7I=,tag:BPUitJtY65JbnanHJgJatg==,type:str]
|
||||
pgp: []
|
||||
encrypted_regex: ^(data|stringData)$
|
||||
version: 3.7.3
|
||||
.dockerconfigjson: |
|
||||
{ "auths": {} }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
resources:
|
||||
- ./image-pull-secret.yaml
|
||||
- ./namespace.yaml
|
||||
- ./auth-deployment.yaml
|
||||
- ./catalog-deployment.yaml
|
||||
- ./runner-deployment.yaml
|
||||
- ./proxy-admin-deployment.yaml
|
||||
- ./proxy-web-deployment.yaml
|
||||
- ./proxy-client-deployment.yaml
|
||||
- ./sync-cronjob.yaml
|
||||
- ./web-client-deployment.yaml
|
||||
- ./admin-client-deployment.yaml
|
||||
|
|
|
|||
|
|
@ -53,5 +53,4 @@ stringData:
|
|||
log_level: 2
|
||||
port: 80
|
||||
endpoints:
|
||||
runner: runner:5001
|
||||
auth: auth:5001
|
||||
runner: runner-local:5001
|
||||
|
|
|
|||
|
|
@ -1,45 +1,45 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: proxy-web
|
||||
name: proxy-client
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
service: proxy-web
|
||||
service: proxy-client
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
service: proxy-web
|
||||
service: proxy-client
|
||||
spec:
|
||||
serviceAccountName: barretthousen-service
|
||||
containers:
|
||||
- name: proxy-web
|
||||
image: barretthousen/service-proxy-web:latest
|
||||
- name: proxy-client
|
||||
image: barretthousen/service-proxy-client:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
command:
|
||||
- /opt/proxy-web
|
||||
- /opt/proxy-client
|
||||
resources:
|
||||
limits:
|
||||
memory: "128Mi"
|
||||
cpu: "250m"
|
||||
volumeMounts:
|
||||
- name: proxy-web-config
|
||||
- name: proxy-client-config
|
||||
mountPath: /config/
|
||||
volumes:
|
||||
- name: proxy-web-config
|
||||
- name: proxy-client-config
|
||||
secret:
|
||||
secretName: proxy-web-config
|
||||
secretName: proxy-client-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: proxy-web
|
||||
name: proxy-client
|
||||
spec:
|
||||
selector:
|
||||
service: proxy-web
|
||||
service: proxy-client
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
|
|
@ -47,11 +47,11 @@ spec:
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: proxy-web-config
|
||||
name: proxy-client-config
|
||||
stringData:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
access_control_allow_origin: "*"
|
||||
endpoints:
|
||||
catalog: catalog:5001
|
||||
auth: auth:5001
|
||||
catalog: catalog-local:5001
|
||||
|
|
@ -46,7 +46,7 @@ spec:
|
|||
ports:
|
||||
- port: 5001
|
||||
targetPort: 5001
|
||||
name: grpc
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
|
|
@ -56,7 +56,6 @@ stringData:
|
|||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 5001
|
||||
catalog_endpoint: catalog:5001
|
||||
db_service:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ kind: CronJob
|
|||
metadata:
|
||||
name: runner-sync
|
||||
spec:
|
||||
schedule: "0 * * * *"
|
||||
schedule: "*/2 * * * *"
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ spec:
|
|||
stdin: true
|
||||
tty: true
|
||||
env:
|
||||
- name: BH_CLIENT_INTERNAL_API_HOST
|
||||
value: "http://proxy-web"
|
||||
- name: ORIGIN
|
||||
value: https://barretthousen.com
|
||||
ports:
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@ namespace: barretthousen-beta
|
|||
|
||||
patchesStrategicMerge:
|
||||
- sync-cronjob.yaml
|
||||
- auth-secret.yaml
|
||||
- catalog-secret.yaml
|
||||
- runner-secret.yaml
|
||||
- proxy-admin-secret.yaml
|
||||
- proxy-web-secret.yaml
|
||||
- proxy-client-secret.yaml
|
||||
- runner-secret.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
|
|
@ -20,7 +19,7 @@ patches:
|
|||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/rules/0/host
|
||||
value: beta.admin.barretthousen.com
|
||||
value: admin.beta.barretthousen.com
|
||||
- target:
|
||||
kind: Ingress
|
||||
name: web
|
||||
|
|
@ -28,13 +27,6 @@ patches:
|
|||
- op: replace
|
||||
path: /spec/rules/0/host
|
||||
value: beta.barretthousen.com
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: auth
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/service-auth:beta
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: catalog
|
||||
|
|
@ -49,7 +41,6 @@ patches:
|
|||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/service-runner:beta
|
||||
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: proxy-admin
|
||||
|
|
@ -59,26 +50,11 @@ patches:
|
|||
value: git.vdhsn.com/barretthousen/service-proxy-admin:beta
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: proxy-web
|
||||
name: proxy-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/service-proxy-web:beta
|
||||
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: admin-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/client-admin-client:beta
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/1/value
|
||||
value: https://beta.admin.barretthousen.com
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/0/value
|
||||
value: http://proxy-admin-beta
|
||||
|
||||
value: git.vdhsn.com/barretthousen/service-proxy-client:beta
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: web-client
|
||||
|
|
@ -86,9 +62,6 @@ patches:
|
|||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/client-web-client:beta
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/1/value
|
||||
value: https://beta.barretthousen.com
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/0/value
|
||||
value: http://proxy-web-beta
|
||||
value: https://beta.barretthousen.com
|
||||
|
|
|
|||
|
|
@ -6,7 +6,5 @@ stringData:
|
|||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
access_control_allow_origin: "beta.admin.barretthousen.com"
|
||||
endpoints:
|
||||
runner: runner-beta:5001
|
||||
auth: auth-beta:5001
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: proxy-web-config
|
||||
name: proxy-client-config
|
||||
stringData:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
access_control_allow_origin: "beta.barretthousen.com"
|
||||
endpoints:
|
||||
auth: auth-beta:5001
|
||||
catalog: catalog-beta:5001
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: auth
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: auth
|
||||
ports:
|
||||
- containerPort: 2345
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: bh-registry
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
stringData:
|
||||
.dockerconfigjson: |
|
||||
{ "auths": {} }
|
||||
|
|
@ -8,16 +8,18 @@ nameSuffix: -local
|
|||
namespace: barretthousen-local
|
||||
|
||||
patchesStrategicMerge:
|
||||
- debug-auth.yaml
|
||||
- debug-catalog.yaml
|
||||
- debug-runner.yaml
|
||||
- runner-secret.yaml
|
||||
- sync-cronjob.yaml
|
||||
- image-pull-secret.yaml
|
||||
- proxy-admin-secret.yaml
|
||||
- proxy-web-secret.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: CronJob
|
||||
name: runner-sync
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/schedule
|
||||
value: "* * * * *"
|
||||
- target:
|
||||
kind: Ingress
|
||||
name: admin
|
||||
|
|
@ -32,23 +34,3 @@ patches:
|
|||
- op: replace
|
||||
path: /spec/rules/0/host
|
||||
value: bh.localhost
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: admin-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/0/value
|
||||
value: http://proxy-admin-local
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/1/value
|
||||
value: http://admin.localhost:8000
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: web-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/0/value
|
||||
value: http://proxy-web-local
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/env/1/value
|
||||
value: http://bh.localhost:8000
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: proxy-web-config
|
||||
stringData:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
endpoints:
|
||||
catalog: catalog-local:5001
|
||||
auth: auth-local:5001
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: auth-config
|
||||
stringData:
|
||||
name: catalog-config
|
||||
data:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 5001
|
||||
|
|
@ -11,8 +11,8 @@ stringData:
|
|||
port: 5432
|
||||
host: bh-db
|
||||
name: bh
|
||||
user: auth-service
|
||||
password: auth-service
|
||||
user: catalog-service
|
||||
password: catalog-service
|
||||
db_migrate:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
|
|
@ -2,19 +2,31 @@ resources:
|
|||
- ../base
|
||||
commonLabels:
|
||||
environment: prod
|
||||
#nameSuffix: -prod
|
||||
namespace: barretthousen
|
||||
|
||||
patchesStrategicMerge:
|
||||
- sync-cronjob.yaml
|
||||
- catalog-configmap.yaml
|
||||
- proxy-admin-configmap.yaml
|
||||
- proxy-client-configmap.yaml
|
||||
- runner-configmap.yaml
|
||||
|
||||
patches:
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: auth
|
||||
kind: Ingress
|
||||
name: admin
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/service-auth:prod
|
||||
path: /spec/rules/0/host
|
||||
value: admin.barretthousen.com
|
||||
- target:
|
||||
kind: Ingress
|
||||
name: web
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/rules/0/host
|
||||
value: barretthousen.com
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: catalog
|
||||
|
|
@ -38,11 +50,11 @@ patches:
|
|||
value: git.vdhsn.com/barretthousen/service-proxy-admin:prod
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: proxy-web
|
||||
name: proxy-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/service-proxy-web:prod
|
||||
value: git.vdhsn.com/barretthousen/service-proxy-client:prod
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: web-client
|
||||
|
|
@ -50,10 +62,6 @@ patches:
|
|||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/client-web-client:prod
|
||||
- target:
|
||||
kind: Deployment
|
||||
name: admin-client
|
||||
patch: |-
|
||||
- op: replace
|
||||
path: /spec/template/spec/containers/0/image
|
||||
value: git.vdhsn.com/barretthousen/client-admin-client:prod
|
||||
path: /spec/template/spec/containers/0/env/0/value
|
||||
value: https://barretthousen.com
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: proxy-admin-config
|
||||
stringData:
|
||||
data:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
endpoints:
|
||||
runner: runner-local:5001
|
||||
auth: auth-local:5001
|
||||
runner: runner-beta:5001
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: proxy-client-config
|
||||
data:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 80
|
||||
access_control_allow_origin: "beta.barretthousen.com"
|
||||
endpoints:
|
||||
catalog: catalog-beta:5001
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
apiVersion: v1
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: runner-config
|
||||
stringData:
|
||||
data:
|
||||
config.yaml: |
|
||||
log_level: 2
|
||||
port: 5001
|
||||
catalog_endpoint: catalog-local:5001
|
||||
catalog_endpoint: catalog-beta:5001
|
||||
db_service:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
|
|
@ -20,4 +20,4 @@ stringData:
|
|||
host: bh-db
|
||||
name: bh
|
||||
user: postgres
|
||||
password: bh-admin
|
||||
password: bh-admin-beta
|
||||
|
|
@ -14,6 +14,6 @@ spec:
|
|||
[
|
||||
"curl",
|
||||
"http://proxy-admin/api/v1/sync",
|
||||
'-d=''{"target":"All"}''',
|
||||
'-d=''{"target":"liveauctioneers"}''',
|
||||
"-vvvv",
|
||||
]
|
||||
|
|
|
|||
3
go.work
3
go.work
|
|
@ -1,10 +1,9 @@
|
|||
go 1.19
|
||||
|
||||
use (
|
||||
./src/auth
|
||||
./src/catalog
|
||||
./src/lib
|
||||
./src/proxy-admin
|
||||
./src/proxy-web
|
||||
./src/proxy-client
|
||||
./src/runner
|
||||
)
|
||||
|
|
|
|||
202
go.work.sum
202
go.work.sum
|
|
@ -1,225 +1,29 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E=
|
||||
cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ=
|
||||
cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw=
|
||||
cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE=
|
||||
cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8=
|
||||
cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8=
|
||||
cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc=
|
||||
cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8=
|
||||
cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E=
|
||||
cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k=
|
||||
cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08=
|
||||
cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw=
|
||||
cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E=
|
||||
cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU=
|
||||
cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss=
|
||||
cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g=
|
||||
cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU=
|
||||
cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU=
|
||||
cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc=
|
||||
cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q=
|
||||
cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8=
|
||||
cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU=
|
||||
cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s=
|
||||
cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA=
|
||||
cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs=
|
||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
||||
cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w=
|
||||
cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA=
|
||||
cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s=
|
||||
cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8=
|
||||
cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE=
|
||||
cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE=
|
||||
cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8=
|
||||
cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM=
|
||||
cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs=
|
||||
cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4=
|
||||
cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c=
|
||||
cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c=
|
||||
cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww=
|
||||
cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ=
|
||||
cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE=
|
||||
cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4=
|
||||
cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs=
|
||||
cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE=
|
||||
cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY=
|
||||
cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU=
|
||||
cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M=
|
||||
cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY=
|
||||
cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg=
|
||||
cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE=
|
||||
cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c=
|
||||
cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0=
|
||||
cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg=
|
||||
cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw=
|
||||
cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw=
|
||||
cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y=
|
||||
cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo=
|
||||
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
|
||||
cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74=
|
||||
cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4=
|
||||
cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE=
|
||||
cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI=
|
||||
cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY=
|
||||
cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo=
|
||||
cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M=
|
||||
cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo=
|
||||
cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA=
|
||||
cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY=
|
||||
cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I=
|
||||
cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM=
|
||||
cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo=
|
||||
cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw=
|
||||
cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM=
|
||||
cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY=
|
||||
cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU=
|
||||
cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ=
|
||||
cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI=
|
||||
cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ=
|
||||
cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc=
|
||||
cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw=
|
||||
cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs=
|
||||
cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk=
|
||||
cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc=
|
||||
cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs=
|
||||
cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4=
|
||||
cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM=
|
||||
cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c=
|
||||
cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac=
|
||||
cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ=
|
||||
cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ=
|
||||
cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI=
|
||||
cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA=
|
||||
cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14=
|
||||
cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg=
|
||||
cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc=
|
||||
cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
|
||||
cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0=
|
||||
cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag=
|
||||
cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk=
|
||||
cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s=
|
||||
cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4=
|
||||
cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA=
|
||||
cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A=
|
||||
cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M=
|
||||
cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI=
|
||||
cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw=
|
||||
cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c=
|
||||
cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc=
|
||||
cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM=
|
||||
cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk=
|
||||
cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos=
|
||||
cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ=
|
||||
cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU=
|
||||
cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0=
|
||||
cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY=
|
||||
cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY=
|
||||
cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes=
|
||||
cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg=
|
||||
cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng=
|
||||
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/elastic/elastic-transport-go/v8 v8.0.0-alpha/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI=
|
||||
github.com/elastic/go-elasticsearch/v8 v8.0.0/go.mod h1:8NCWP26meGbncX+R9sxo2JD8IqBjRTuS7yXMstHpd40=
|
||||
github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
|
||||
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
||||
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.uber.org/dig v1.0.0/go.mod h1:z+dSd2TP9Usi48jL8M3v63iSBVkiwtVyMKxMZYYauPg=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
build(){
|
||||
export ENV=${1:-beta}; # if not specified, will only build and push for the git commit
|
||||
make build-backend-image SERVICE=auth &
|
||||
make build-backend-image SERVICE=catalog &
|
||||
make build-backend-image SERVICE=runner &
|
||||
make build-backend-image SERVICE=proxy-admin &
|
||||
make build-backend-image SERVICE=proxy-web &
|
||||
time wait;
|
||||
|
||||
# for prod drop `beta prefix
|
||||
make build-client-image SERVICE=web-client &
|
||||
make build-client-image SERVICE=admin-client &
|
||||
time wait;
|
||||
|
||||
kubectl rollout restart -n barretthousen-beta deployment runner-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment catalog-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment auth-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment proxy-admin-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment proxy-web-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment web-client-beta &
|
||||
kubectl rollout restart -n barretthousen-beta deployment admin-client-beta &
|
||||
|
||||
kubectl rollout status -n barretthousen-beta deployment runner-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment catalog-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment auth-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment proxy-admin-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment proxy-web-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment admin-client-beta -w
|
||||
kubectl rollout status -n barretthousen-beta deployment web-client-beta -w
|
||||
}
|
||||
|
||||
promote() {
|
||||
make promote-backend-prod SERVICE=catalog &
|
||||
make promote-backend-prod SERVICE=runner &
|
||||
make promote-backend-prod SERVICE=auth &
|
||||
make promote-backend-prod SERVICE=proxy-admin &
|
||||
make promote-backend-prod SERVICE=proxy-web &
|
||||
|
||||
make promote-client-prod SERVICE=web-client &
|
||||
make promote-client-prod SERVICE=admin-client &
|
||||
|
||||
time wait;
|
||||
|
||||
kubectl rollout restart -n barretthousen deployment runner &
|
||||
kubectl rollout restart -n barretthousen deployment catalog &
|
||||
kubectl rollout restart -n barretthousen deployment auth &
|
||||
kubectl rollout restart -n barretthousen deployment proxy-admin &
|
||||
kubectl rollout restart -n barretthousen deployment proxy-web &
|
||||
kubectl rollout restart -n barretthousen deployment web-client &
|
||||
kubectl rollout restart -n barretthousen deployment admin-client &
|
||||
|
||||
kubectl rollout status -n barretthousen deployment runner -w
|
||||
kubectl rollout status -n barretthousen deployment catalog -w
|
||||
kubectl rollout status -n barretthousen deployment auth -w
|
||||
kubectl rollout status -n barretthousen deployment proxy-admin -w
|
||||
kubectl rollout status -n barretthousen deployment proxy-web -w
|
||||
kubectl rollout status -n barretthousen deployment admin-client -w
|
||||
kubectl rollout status -n barretthousen deployment web-client -w
|
||||
}
|
||||
|
||||
build $@
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
main(){
|
||||
local EMAIL=${1};
|
||||
if [ -z "${EMAIL}" ]; then
|
||||
echo "first argument must be an EMAIL address"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
local PASSWORD=${2};
|
||||
if [ -z "${PASSWORD}" ]; then
|
||||
echo "second argument must be a PASSWORD"
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
local ROLE=${3:-USER};
|
||||
local HOST=${4:-"http://bh.localhost:8000"};
|
||||
|
||||
curl -X PUT -H 'Content-Type: application/json' \
|
||||
-d "{ \"email\":\"${EMAIL}\", \"password\":\"${PASSWORD}\", \"role\":\"${ROLE}\" }" \
|
||||
"${HOST}/api/v1/user";
|
||||
}
|
||||
|
||||
|
||||
main $@;
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker run --rm \
|
||||
-e DRONE_COMMIT_REF=refs/heads/trunk \
|
||||
-e DRONE_REPO_BRANCH=trunk \
|
||||
-e PLUGIN_REGISTRY=git.vdhsn.com \
|
||||
-e PLUGIN_REPO=git.vdhsn.com/barretthousen/service-catalog \
|
||||
-e PLUGIN_BUILD_ARGS="service=catalog" \
|
||||
-e PLUGIN_TAGS=$(git rev-parse --verify --short HEAD) \
|
||||
-e PLUGIN_CONTEXT="./src" \
|
||||
-e PLUGIN_DOCKERFILE="./src/Dockerfile.prod-backend" \
|
||||
-e PLUGIN_USERNAME=${DOCKER_USERNAME} \
|
||||
-e PLUGIN_PASSWORD=${DOCKER_PASSWORD} \
|
||||
-e PLUGIN_ENABLE_CACHE=true \
|
||||
-e PLUGIN_CACHE_REPO='git.vdhsn.com/barretthousen/ci-cache' \
|
||||
-e PLUGIN_SKIP_UNUSED_STAGES=true \
|
||||
-v $(pwd):/drone \
|
||||
-w /drone \
|
||||
plugins/kaniko:linux-amd64
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
main(){
|
||||
local REPOSITORY=${1};
|
||||
if [ -z "${REPOSITORY}" ]; then
|
||||
echo "First argument must be container repository";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
local FROM=${2:-beta};
|
||||
local TO=${3:-prod};
|
||||
|
||||
local CONTENT_TYPE="application/vnd.docker.distribution.manifest.v2+json";
|
||||
local REGISTRY_URL="https://git.vdhsn.com/v2/${REPOSITORY}/manifests";
|
||||
|
||||
export MANIFEST=$(curl -u "${DOCKER_USERNAME}:${DOCKER_PASSWORD}" \
|
||||
-H "Accept: ${CONTENT_TYPE}" "${REGISTRY_URL}/${FROM}");
|
||||
|
||||
|
||||
curl -u "${DOCKER_USERNAME}:${DOCKER_PASSWORD}" \
|
||||
-X PUT -H "Content-Type: ${CONTENT_TYPE}" -d "${MANIFEST}" "${REGISTRY_URL}/${TO}";
|
||||
|
||||
echo "";
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,2 @@
|
|||
web-client
|
||||
.idea
|
||||
web-client/*
|
||||
admin-client/*
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.19-alpine as dev-builder
|
||||
FROM golang:1.19-alpine as builder
|
||||
|
||||
ARG service
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ FROM alpine as development
|
|||
|
||||
ARG service
|
||||
|
||||
COPY --from=dev-builder /go/bin/dlv /go/bin/dlv
|
||||
COPY --from=builder /go/bin/dlv /go/bin/dlv
|
||||
COPY .bin/${service}-debug /opt/
|
||||
COPY ./src /go/src/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
FROM node:lts AS development
|
||||
|
||||
ARG service
|
||||
|
||||
COPY . /opt/${service}
|
||||
|
||||
WORKDIR /opt/${service}
|
||||
|
||||
RUN npm install && npm install -g vite
|
||||
|
||||
CMD vite dev --port=80 --host=0.0.0.0 --strictPort --logLevel info
|
||||
|
||||
FROM node:lts AS build
|
||||
|
||||
ARG service
|
||||
|
||||
ENV PROTOCOL_HEADER=x-forwarded-proto
|
||||
ENV HOST_HEADER=x-forwarded-host
|
||||
|
||||
WORKDIR /opt/${service}
|
||||
|
||||
COPY . /opt/${service}
|
||||
|
||||
RUN npm ci && npm run build \
|
||||
&& cp -v /opt/${service}/package.json /opt/${service}/build \
|
||||
&& cp -v /opt/${service}/package-lock.json /opt/${service}/build \
|
||||
&& cd /opt/${service}/build && npm ci --omit dev
|
||||
|
||||
FROM node:lts AS production
|
||||
|
||||
ARG service
|
||||
|
||||
LABEL com.barretthousen.service=${service}
|
||||
LABEL com.barretthousen.tags="frontend,public"
|
||||
LABEL com.barretthousen.release-date="2023-05-01"
|
||||
LABEL com.barretthousen.version="alpha-0.0.1"
|
||||
LABEL com.barretthousen.git-ref="000000000000000000000000000000000000000000000000"
|
||||
|
||||
ENV ENV=production
|
||||
ENV PROTOCOL_HEADER=x-forwarded-proto
|
||||
ENV HOST_HEADER=x-forwarded-host
|
||||
ENV BH_CLIENT_SERVICE=${service}
|
||||
ENV ORIGIN="https://barretthousen.com"
|
||||
|
||||
|
||||
COPY --from=build /opt/${service}/build/ /opt/${service}/
|
||||
|
||||
WORKDIR /opt/${service}
|
||||
|
||||
ENV PORT 80
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["node", "."]
|
||||
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
FROM git.vdhsn.com/barretthousen/tools:v1 as prod-builder
|
||||
FROM golang:1.19 as builder
|
||||
|
||||
|
||||
RUN go install github.com/bufbuild/buf/cmd/buf@v1.17.0
|
||||
RUN go install github.com/kyleconroy/sqlc/cmd/sqlc@latest
|
||||
|
||||
COPY . /go/src
|
||||
|
||||
WORKDIR /go/src/
|
||||
|
||||
COPY . /go/src/
|
||||
|
||||
RUN /go/bin/sqlc generate -f /go/src/sqlc.yaml \
|
||||
&& /go/bin/buf mod update /go/src && /go/bin/buf generate
|
||||
RUN /go/bin/sqlc generate -f /go/src/sqlc.yaml
|
||||
RUN /go/bin/buf mod update /go/src && /go/bin/buf generate
|
||||
|
||||
ARG service
|
||||
|
||||
|
|
@ -18,7 +22,7 @@ FROM alpine as production
|
|||
|
||||
ARG service
|
||||
|
||||
COPY --from=prod-builder /opt/${service} /opt/${service}
|
||||
COPY --from=builder /opt/${service} /opt/${service}
|
||||
|
||||
ENV SERVICE=${SERVICE}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.19
|
||||
FROM golang:1.19-alpine as builder
|
||||
|
||||
RUN go install github.com/bufbuild/buf/cmd/buf@v1.17.0
|
||||
RUN go install github.com/kyleconroy/sqlc/cmd/sqlc@latest
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
FROM node:lts AS development
|
||||
|
||||
COPY . /opt/admin-client
|
||||
|
||||
WORKDIR /opt/admin-client
|
||||
|
||||
RUN npm install && npm install -g vite
|
||||
|
||||
CMD vite dev --port=80 --host=0.0.0.0 --strictPort --logLevel info
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
FROM node:lts AS build
|
||||
|
||||
ARG origin=https://barretthousen.com
|
||||
|
||||
ENV PROTOCOL_HEADER=x-forwarded-proto
|
||||
ENV HOST_HEADER=x-forwarded-host
|
||||
ENV ORIGIN=${origin}
|
||||
|
||||
WORKDIR /opt/admin-client
|
||||
|
||||
COPY . /opt/admin-client
|
||||
|
||||
RUN npm run build \
|
||||
&& cp -v /opt/admin-client/package.json /opt/admin-client/build \
|
||||
&& cp -v /opt/admin-client/package-lock.json /opt/admin-client/build \
|
||||
&& cd /opt/admin-client/build && npm ci --omit dev
|
||||
|
||||
FROM node:lts AS production
|
||||
|
||||
LABEL com.barretthousen.service="admin-client"
|
||||
LABEL com.barretthousen.tags="frontend,public"
|
||||
LABEL com.barretthousen.release-date="2023-05-01"
|
||||
LABEL com.barretthousen.version="alpha-0.0.1"
|
||||
LABEL com.barretthousen.git-ref="000000000000000000000000000000000000000000000000"
|
||||
|
||||
ARG origin=https://barretthousen.com
|
||||
|
||||
ENV ENV=production
|
||||
ENV PROTOCOL_HEADER=x-forwarded-proto
|
||||
ENV HOST_HEADER=x-forwarded-host
|
||||
ENV ORIGIN=${origin}
|
||||
|
||||
WORKDIR /opt
|
||||
|
||||
COPY --from=build /opt/admin-client/build/ /opt/admin-client/
|
||||
|
||||
ENV PORT 80
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["node", "admin-client"]
|
||||
|
||||
|
|
@ -1,12 +1,38 @@
|
|||
# Admin client
|
||||
# create-svelte
|
||||
|
||||
Admin panel to drive backend "administrative" functionality
|
||||
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
|
||||
|
||||
Uses [SvelteKit](), [TailwindCSS](), [Typescript (poorly)]()
|
||||
## Creating a project
|
||||
|
||||
If you're seeing this, you've probably already done this step. Congrats!
|
||||
|
||||
## Development
|
||||
```bash
|
||||
# create a new project in the current directory
|
||||
npm create svelte@latest
|
||||
|
||||
Follow the [Contributing section](../../README.md#contributing) to get the environment stood up locally.
|
||||
# create a new project in my-app
|
||||
npm create svelte@latest my-app
|
||||
```
|
||||
|
||||
Browse to [http://admin.localhost:8000](http://admin.localhost:8000).
|
||||
## Developing
|
||||
|
||||
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
|
||||
# or start the server and open the app in a new browser tab
|
||||
npm run dev -- --open
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
To create a production version of your app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can preview the production build with `npm run preview`.
|
||||
|
||||
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "adminb-client",
|
||||
"name": "web-client",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "adminb-client",
|
||||
"name": "web-client",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"luxon": "^3.3.0"
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
interface FormValidations {
|
||||
email?: boolean;
|
||||
general?: boolean;
|
||||
}
|
||||
|
||||
export const validations: FormValidations = {};
|
||||
|
||||
let email: string = '';
|
||||
let password: string = '';
|
||||
let passwordConfirmation: string = '';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const execLogin = () =>
|
||||
dispatch('login', {
|
||||
email,
|
||||
password
|
||||
});
|
||||
|
||||
const execRegister = () => {
|
||||
if (password !== passwordConfirmation) {
|
||||
console.log("password and confirm don't match");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch('register', {
|
||||
email,
|
||||
password
|
||||
});
|
||||
};
|
||||
|
||||
let showPassword = false;
|
||||
let showRegistration = false;
|
||||
|
||||
const revealPass = () => (showPassword = !showPassword);
|
||||
const toggleFormType = () => (showRegistration = !showRegistration);
|
||||
|
||||
$: ctaTxt = showRegistration ? 'Up' : 'In';
|
||||
$: toggleCtaTxt = !showRegistration ? 'Up' : 'In';
|
||||
$: ctaFunc = showRegistration ? execRegister : execLogin;
|
||||
</script>
|
||||
|
||||
<form class="flex" style="max-width: 600px;" on:submit|preventDefault={ctaFunc}>
|
||||
<span class="flex flex-col justify-around w-20">
|
||||
<label for="email"> Email </label>
|
||||
<label for="password"> Password </label>
|
||||
</span>
|
||||
|
||||
<span class="flex flex-col">
|
||||
<span class="flex">
|
||||
<input
|
||||
class="px-2 py-1 border-r-0 grow invalid:border-red-500 invalid:border-2"
|
||||
type="email"
|
||||
required
|
||||
bind:value={email}
|
||||
/>
|
||||
<button class="border-l-0 px-2 py-1 disabled:text-gray-500">
|
||||
Sign {ctaTxt}
|
||||
</button>
|
||||
</span>
|
||||
<span class="flex">
|
||||
<input
|
||||
class="px-2 py-1 w-full"
|
||||
name="password"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
required
|
||||
placeholder={showRegistration ? 'Password' : ''}
|
||||
on:blur={() => (showPassword = false)}
|
||||
on:change={(evt) => (password = evt?.target?.value)}
|
||||
/>
|
||||
{#if showRegistration}
|
||||
<input
|
||||
class="px-2 py-1 border-r-0 invalid:border-red-500 invalid:border-2"
|
||||
name="confirm_password"
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
pattern={password}
|
||||
required
|
||||
placeholder="Confirm Password"
|
||||
on:blur={() => (showPassword = false)}
|
||||
on:change={(evt) => (passwordConfirmation = evt?.target?.value)}
|
||||
/>
|
||||
|
||||
<button
|
||||
class="border-l-0 px-2 py-1 w-16"
|
||||
tabindex="-1"
|
||||
on:click|stopPropagation={revealPass}
|
||||
>
|
||||
{showPassword ? 'Hide' : 'Show'}
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
</span>
|
||||
</form>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
export let page: number = 1;
|
||||
export let itemCount: number = 0;
|
||||
export let pageSize: number = 1;
|
||||
|
||||
interface PagerParams {
|
||||
page: number;
|
||||
pageCount: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
export let createUrl: (
|
||||
//<reference types="svelte" />
|
||||
arg0: PagerParams
|
||||
) => string = (): string => '';
|
||||
|
||||
$: pageCount = Math.max(1, Math.ceil(itemCount / pageSize));
|
||||
</script>
|
||||
|
||||
<ol class="flex justify-between w-full center text-lg" style="padding: 0 10%;">
|
||||
{#if page > 1}
|
||||
<li in:fade>
|
||||
<a href={createUrl({ page: page - 1, pageCount, pageSize })}> <Previous </a>
|
||||
</li>
|
||||
{:else}
|
||||
<li />
|
||||
{/if}
|
||||
<li>Page {page} of {pageCount}</li>
|
||||
{#if page < pageCount}
|
||||
<li in:fade>
|
||||
<a href={createUrl({ page: page + 1, pageCount, pageSize })}> Next> </a>
|
||||
</li>
|
||||
{:else}
|
||||
<li />
|
||||
{/if}
|
||||
</ol>
|
||||
|
|
@ -1,14 +1,12 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let disable: boolean = false;
|
||||
|
||||
let target: string = 'All';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function execScrape() {
|
||||
if (!disable) dispatch('scrape', { target });
|
||||
dispatch('scrape', { target });
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -17,7 +15,6 @@
|
|||
<option>All</option>
|
||||
<option>liveauctioneers</option>
|
||||
</select>
|
||||
<button class="border-none rounded-r-md bg-bh-gold text-bh-black py-1 px-2" disabled={disable}
|
||||
>Start Sync</button
|
||||
>
|
||||
|
||||
<button class="border-none rounded-r-md bg-bh-gold text-bh-black py-1 px-2">Start Sync</button>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -1,119 +0,0 @@
|
|||
import { browser } from '$app/environment';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
const API_HOST = `${browser ? '' : env.BH_CLIENT_INTERNAL_API_HOST}/api/v1`;
|
||||
|
||||
interface SessionInfo {
|
||||
sessionId?: string;
|
||||
account?: {
|
||||
id: string;
|
||||
email: string;
|
||||
role: 'BIDDER' | 'USER' | 'ADMINISTRATOR' | 'ANONYMOUS';
|
||||
createdTs: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const getSession = () => {
|
||||
if (browser) {
|
||||
const strSession = localStorage.getItem('bh-session');
|
||||
if (strSession) {
|
||||
const data = JSON.parse(strSession);
|
||||
if (data?.sessionId) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
export const session = writable<SessionInfo>(getSession(), (set) => {
|
||||
const session = getSession();
|
||||
if (session) {
|
||||
set(session);
|
||||
}
|
||||
});
|
||||
|
||||
interface LoginAction {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export const loginAction = async ({ email, password }: LoginAction): Promise<SessionInfo> => {
|
||||
try {
|
||||
const sessionStr = localStorage.getItem('bh-session');
|
||||
if (sessionStr) {
|
||||
const data = JSON.parse(sessionStr);
|
||||
if (data.sessionId) {
|
||||
console.log('already authenticated');
|
||||
session.set(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
localStorage.removeItem('bh-session');
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
new Request(`${API_HOST}/user`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
password
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
|
||||
if (data.sessionId) {
|
||||
localStorage.setItem('bh-session', JSON.stringify(data));
|
||||
return data;
|
||||
}
|
||||
|
||||
console.trace("got this on login attempt:", data);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
interface RegisterAction {
|
||||
email: string;
|
||||
password: string;
|
||||
role?: string;
|
||||
}
|
||||
export const registerAction = async ({ email, password, role }: RegisterAction) => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
new Request(`${API_HOST}/user`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
password,
|
||||
role: role || 'USER'
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
export const logoutAction = () => {
|
||||
localStorage.removeItem('bh-session');
|
||||
session.set({});
|
||||
};
|
||||
|
|
@ -1,34 +1,5 @@
|
|||
<script lang="ts">
|
||||
import '../app.css';
|
||||
|
||||
import AuthForm from '$lib/AuthForm.svelte';
|
||||
|
||||
import { loginAction, logoutAction, registerAction, session } from '$lib/state';
|
||||
|
||||
async function onLogin(evt: CustomEvent) {
|
||||
const { email, password } = evt.detail;
|
||||
await loginAction({ email, password });
|
||||
}
|
||||
|
||||
async function onLogout() {
|
||||
logoutAction();
|
||||
}
|
||||
|
||||
interface SessionInfo {
|
||||
sessionId?: string;
|
||||
account?: {
|
||||
id: string;
|
||||
email: string;
|
||||
role: 'BIDDER' | 'USER' | 'ADMINISTRATOR' | 'ANONYMOUS';
|
||||
createdTs: string;
|
||||
};
|
||||
}
|
||||
|
||||
let sessionVal: SessionInfo;
|
||||
|
||||
session.subscribe((v) => (sessionVal = v));
|
||||
|
||||
$: isLoggedIn = !!sessionVal?.sessionId;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
@ -55,19 +26,8 @@
|
|||
<li class="flex grow justify-center">
|
||||
<span class="flex grow" style="max-width: 75%;"> Admin Stuff </span>
|
||||
</li>
|
||||
<li class="pr-5">
|
||||
<li class="px-6">
|
||||
<!-- <span>I want email alerts!</span> -->
|
||||
{#if !isLoggedIn}
|
||||
<AuthForm on:login={onLogin} />
|
||||
{:else}
|
||||
<span>
|
||||
{sessionVal.account?.email}
|
||||
</span>
|
||||
<button
|
||||
class="bg-bh-gold border-bh-black px-2 py-1 text-bh-black"
|
||||
on:click|stopPropagation={onLogout}>Log out</button
|
||||
>
|
||||
{/if}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -1,96 +1,61 @@
|
|||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
import StartScrapeForm from '$lib/StartScrapeForm.svelte';
|
||||
import ScrapeJobResult from '$lib/ScrapeJobResult.svelte';
|
||||
import Pager from '$lib/Pager.svelte';
|
||||
|
||||
import { fade } from 'svelte/transition';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
import { getSession } from '$lib/state';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
$: activeJobCount = data.active.length;
|
||||
|
||||
let disableSync = false;
|
||||
|
||||
var intervalId: any;
|
||||
onMount(() => {
|
||||
intervalId = setInterval(invalidateAll, 2000);
|
||||
});
|
||||
onDestroy(() => clearInterval(intervalId));
|
||||
$: completedJobs = data.jobs.filter(({ completedTs }) => completedTs !== null);
|
||||
$: activeJobs = data.jobs.filter(({ completedTs }) => completedTs === null);
|
||||
$: activeJobCount = activeJobs.length;
|
||||
$: completedJobCount = completedJobs.length;
|
||||
|
||||
async function onScrape({ detail }) {
|
||||
disableSync = true;
|
||||
try {
|
||||
const response = await fetch(
|
||||
new Request('/api/v1/sync', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'bh-session-id': getSession()?.sessionId
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ targetSite: detail.target })
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
} finally {
|
||||
disableSync = false;
|
||||
}
|
||||
}
|
||||
|
||||
function buildQueryString({ page, pageSize }: { page: number; pageSize: number }): string {
|
||||
const qs = [
|
||||
data.query === '' ? data.query : `query=${data.query}`,
|
||||
page <= 1 ? '' : `page=${page}`,
|
||||
`limit=${pageSize}`
|
||||
]
|
||||
.filter((x) => x !== '')
|
||||
.join('&');
|
||||
|
||||
return qs !== '' ? `/?${qs}` : qs;
|
||||
const scrapeJob = await response.json();
|
||||
data.jobs.push(scrapeJob);
|
||||
console.log(scrapeJob);
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
const limit = 16;
|
||||
</script>
|
||||
|
||||
<section class="flex w-full flex-col justify-center" in:fade out:fade>
|
||||
<section in:fade>
|
||||
<h1 class="text-2xl pb-5">Sync Status: {data.total} jobs</h1>
|
||||
</section>
|
||||
<section class="pb-5">
|
||||
<h2 class="text-2xl">{activeJobCount} In Progress</h2>
|
||||
{#key data.activeTotal}
|
||||
<ul class="flex">
|
||||
{#each data.active as job, i}
|
||||
<li id="job-{job.id}" in:fade={{ delay: i * 90 }}>
|
||||
<ScrapeJobResult {job} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/key}
|
||||
</section>
|
||||
<StartScrapeForm on:scrape={onScrape} disable={disableSync} />
|
||||
<section class="py-10">
|
||||
<h2 class="text-2xl">Completed</h2>
|
||||
<Pager
|
||||
page={data.page}
|
||||
itemCount={data.completeTotal}
|
||||
pageSize={limit}
|
||||
createUrl={buildQueryString}
|
||||
/>
|
||||
{#key data.completeTotal + data.page}
|
||||
<ul class="flex flex-wrap justify-between">
|
||||
{#each data.complete as job, i}
|
||||
<li id="job-{job.id}" in:fade={{ delay: i * 90 }}>
|
||||
<ScrapeJobResult {job} />
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/key}
|
||||
</section>
|
||||
<h1 class="text-2xl mb-8">Sync Status</h1>
|
||||
<div class="mb-8">
|
||||
<StartScrapeForm on:scrape={onScrape} />
|
||||
</div>
|
||||
<section>
|
||||
<Pager page={data.page} itemCount={data.total} pageSize={limit} createUrl={buildQueryString} />
|
||||
<h2>{activeJobCount} In Progress Jobs</h2>
|
||||
<ul class="flex">
|
||||
{#each activeJobs as j, i}
|
||||
<li in:fade>
|
||||
<ScrapeJobResult job={j} />
|
||||
</li>
|
||||
<!-- {#if i < 10}
|
||||
{/if} -->
|
||||
{/each}
|
||||
</ul>
|
||||
<h2>{completedJobCount} Complete</h2>
|
||||
<ul class="flex flex-wrap justify-between">
|
||||
{#each completedJobs as j, i}
|
||||
<li in:fade>
|
||||
<ScrapeJobResult job={j} />
|
||||
</li>
|
||||
<!-- {#if i < 5}
|
||||
{/if} -->
|
||||
{/each}
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { browser } from '$app/environment';
|
||||
import type { PageLoad } from './$types';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import { getSession } from '$lib/state';
|
||||
|
||||
const API_HOST = `${browser ? '' : env.BH_CLIENT_INTERNAL_API_HOST}/api/v1`;
|
||||
// TODO: change to env var
|
||||
const API_HOST = `${browser ? '' : 'http://proxy-admin-local'}/api/v1`;
|
||||
|
||||
|
||||
interface Job {
|
||||
id: Number;
|
||||
|
|
@ -15,89 +15,18 @@ interface Job {
|
|||
}
|
||||
|
||||
interface ScrapeStatusPageData {
|
||||
page: number;
|
||||
total: number;
|
||||
activeTotal: number;
|
||||
completeTotal: number;
|
||||
limit: number;
|
||||
active: Job[];
|
||||
complete: Job[];
|
||||
jobs: Job[]
|
||||
}
|
||||
|
||||
export const load = (async ({ fetch, url }): Promise<ScrapeStatusPageData> => {
|
||||
const searchParams = new SearchParameters(url);
|
||||
const limit = searchParams.getLimit();
|
||||
|
||||
console.log(getSession());
|
||||
try {
|
||||
const response = await fetch(
|
||||
new Request(API_HOST + `/sync${searchParams.toQueryString()}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'bh-session-id': getSession()?.sessionId,
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
);
|
||||
const { active, complete, activeTotal, completeTotal, total, page } = await response.json();
|
||||
|
||||
const response = await fetch(API_HOST + `/sync`);
|
||||
const {results } = await response.json();
|
||||
return {
|
||||
active,
|
||||
complete,
|
||||
activeTotal,
|
||||
completeTotal,
|
||||
total,
|
||||
page,
|
||||
limit
|
||||
jobs: results || []
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return {
|
||||
activeTotal: 0,
|
||||
completeTotal: 0,
|
||||
active: [],
|
||||
complete: [],
|
||||
total: 0,
|
||||
page: 1,
|
||||
limit
|
||||
};
|
||||
return { jobs:[] };
|
||||
}
|
||||
}) satisfies PageLoad;
|
||||
|
||||
class SearchParameters {
|
||||
page: number;
|
||||
limit: number;
|
||||
|
||||
constructor(url: URL) {
|
||||
this.page = Number(url.searchParams.get('page') || 1);
|
||||
if (this.page < 0) {
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
this.limit = Number(url.searchParams.get('limit') || 12);
|
||||
if (this.limit > 32) {
|
||||
this.limit = 32;
|
||||
} else if (this.limit < 12) {
|
||||
this.limit = 12;
|
||||
}
|
||||
}
|
||||
|
||||
getPage(): number {
|
||||
return this.page || 1;
|
||||
}
|
||||
|
||||
getLimit(): number {
|
||||
return this.limit || 12;
|
||||
}
|
||||
|
||||
toQueryString(): string {
|
||||
const qs = Object.entries(this)
|
||||
.filter((t) => t.length > 0 && t[1])
|
||||
.map((t) => `${t[0]}=${t[1]}`)
|
||||
.join('&');
|
||||
return qs === '' ? '' : `?${qs}`;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const config = {
|
|||
|
||||
kit: {
|
||||
env: {
|
||||
publicPrefix: 'BH_CLIENT'
|
||||
publicPrefix: 'BH_WEB_CLIENT'
|
||||
},
|
||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
tests:
|
||||
- description: "Register User"
|
||||
request:
|
||||
path: "/v1/user"
|
||||
method: "PUT"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
- description: "Login"
|
||||
request:
|
||||
path: "/v1/user"
|
||||
method: "POST"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
- description: "Account Details"
|
||||
request:
|
||||
path: "/v1/user"
|
||||
method: "GET"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
- description: "Verify Account"
|
||||
request:
|
||||
path: "/v1/user/verify"
|
||||
method: "GET"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
aapi "git.vdhsn.com/barretthousen/barretthousen/src/auth/api/grpc"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/domain"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func NewAuthServiceClient(conn grpc.ClientConnInterface) *AuthServiceClient {
|
||||
return &AuthServiceClient{
|
||||
AuthClient: aapi.NewAuthClient(conn),
|
||||
}
|
||||
}
|
||||
|
||||
type AuthServiceClient struct {
|
||||
aapi.AuthClient
|
||||
}
|
||||
|
||||
type CheckSessionParams struct {
|
||||
SessionID string
|
||||
}
|
||||
|
||||
func (asc *AuthServiceClient) CheckSession(ctx context.Context, in CheckSessionParams) (out Account, err error) {
|
||||
if in.SessionID == "" {
|
||||
err = domain.ErrInvalidSession
|
||||
return
|
||||
}
|
||||
var sessionIDInt int
|
||||
|
||||
if sessionIDInt, err = strconv.Atoi(in.SessionID); err != nil {
|
||||
return
|
||||
}
|
||||
var accountResult *aapi.Account
|
||||
|
||||
if accountResult, err = asc.GetSession(ctx, &aapi.SessionFilter{
|
||||
SessionId: int32(sessionIDInt),
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out = Account{
|
||||
ID: int(accountResult.Id),
|
||||
Created: accountResult.CreatedTs.AsTime(),
|
||||
Email: accountResult.Email,
|
||||
Verified: accountResult.VerifiedTs.AsTime(),
|
||||
Role: accountResult.Role,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
ID int `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Verified time.Time `json:"verified,omitempty"`
|
||||
Email string `json:"email"`
|
||||
PasswordHash string `json:"password_hash,omitempty"`
|
||||
Role string `json:"role"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package main;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option go_package = "git.vdhsn.com/barretthousen/barretthousen/src/auth/api/grpc";
|
||||
|
||||
service Auth {
|
||||
rpc CreateAccount(CreateAccountInput) returns (Account) {
|
||||
option (google.api.http) = {
|
||||
put: "/v1/user"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc Login(LoginInput) returns (LoginResult) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/user"
|
||||
body: "*"
|
||||
};
|
||||
}
|
||||
|
||||
rpc VerifyAccount(VerificationParameters) returns (AccountVerifiedResult) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/user/verify"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetAccount(AccountFilter) returns (Account) {
|
||||
option (google.api.http) = {
|
||||
get: "/v1/user"
|
||||
};
|
||||
}
|
||||
|
||||
rpc GetSession(SessionFilter) returns (Account) { }
|
||||
}
|
||||
|
||||
message SessionFilter {
|
||||
int32 sessionId = 1;
|
||||
}
|
||||
|
||||
message CreateAccountInput {
|
||||
string email = 1;
|
||||
string password = 2;
|
||||
string role = 3;
|
||||
}
|
||||
|
||||
message LoginInput {
|
||||
string email = 1;
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message LoginResult {
|
||||
string sessionId = 1;
|
||||
Account account = 2;
|
||||
}
|
||||
|
||||
message AccountFilter {
|
||||
int32 id = 1;
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
message VerificationParameters {
|
||||
string token = 1;
|
||||
string email = 2;
|
||||
}
|
||||
|
||||
message AccountVerifiedResult {}
|
||||
|
||||
message Account {
|
||||
int32 id = 1;
|
||||
string email = 2;
|
||||
string role = 3;
|
||||
google.protobuf.Timestamp createdTs = 4;
|
||||
google.protobuf.Timestamp verifiedTs = 5;
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
module git.vdhsn.com/barretthousen/barretthousen/src/auth
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
git.vdhsn.com/barretthousen/barretthousen/src/lib v1.0.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
|
||||
go.uber.org/dig v1.16.1
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1
|
||||
google.golang.org/protobuf v1.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/ilyakaznacheev/cleanenv v1.4.2 // indirect
|
||||
github.com/jackc/puddle v1.3.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/pressly/goose/v3 v3.11.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||
github.com/jackc/pgconn v1.14.0
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.1
|
||||
go.uber.org/automaxprocs v1.5.2 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/grpc v1.55.0
|
||||
)
|
||||
|
||||
replace git.vdhsn.com/barretthousen/barretthousen/src/lib v1.0.0 => ../lib
|
||||
262
src/auth/go.sum
262
src/auth/go.sum
|
|
@ -1,262 +0,0 @@
|
|||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2/go.mod h1:7pdNwVWBBHGiCxa9lAszqCJMbfTISJ7oMftp8+UGV08=
|
||||
github.com/ilyakaznacheev/cleanenv v1.4.2 h1:nRqiriLMAC7tz7GzjzUTBHfzdzw6SQ7XvTagkFqe/zU=
|
||||
github.com/ilyakaznacheev/cleanenv v1.4.2/go.mod h1:i0owW+HDxeGKE0/JPREJOdSCPIyOnmh6C0xhWAkF/xA=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
|
||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
|
||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
|
||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
|
||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
|
||||
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
|
||||
github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q=
|
||||
github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
|
||||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc=
|
||||
github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
|
||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0=
|
||||
github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
|
||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||
github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw=
|
||||
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
|
||||
github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/pressly/goose/v3 v3.11.0 h1:krazmHhfT6SxJGqtTjddwTsL2Xwje2piTQYRH8KLECI=
|
||||
github.com/pressly/goose/v3 v3.11.0/go.mod h1:ofR04pV2CYY1q/y7CNjoFQuzW4lGSVKwMI/m9lnAjVo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
|
||||
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||
go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8=
|
||||
go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
|
||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
||||
modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU=
|
||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 h1:slmdOY3vp8a7KQbHkL+FLbvbkgMqmXojpFUO/jENuqQ=
|
||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw=
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
-- +goose Up
|
||||
START TRANSACTION;
|
||||
|
||||
CREATE SCHEMA IF NOT EXISTS auth;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auth.account (
|
||||
id SERIAL PRIMARY KEY,
|
||||
createdTs TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
verifiedTs TIMESTAMP NULL,
|
||||
email VARCHAR(512) NOT NULL,
|
||||
passwordHash VARCHAR(512) NOT NULL,
|
||||
role VARCHAR(64) NOT NULL DEFAULT 'BIDDER',
|
||||
enabled BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auth.account_verification (
|
||||
id SERIAL PRIMARY KEY,
|
||||
accountId INT NOT NULL,
|
||||
createdTs TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
verificationToken VARCHAR(128) NOT NULL UNIQUE,
|
||||
CONSTRAINT fk_account_id FOREIGN KEY (accountId) REFERENCES auth.account(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS auth.sessions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
accountId INT NOT NULL,
|
||||
createdTs TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT fk_account_id FOREIGN KEY (accountId) REFERENCES auth.account(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE OR REPLACE FUNCTION auth.bh_register_account(
|
||||
p_email VARCHAR(512),
|
||||
p_passwordHash VARCHAR(512),
|
||||
p_role VARCHAR(64))
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql AS $BODY$
|
||||
DECLARE
|
||||
account_id INTEGER;
|
||||
BEGIN
|
||||
SELECT acc.id INTO account_id FROM auth.account acc WHERE acc.email = p_email;
|
||||
|
||||
IF account_id IS NULL OR account_id = 0 THEN
|
||||
INSERT INTO auth.account (
|
||||
email,
|
||||
passwordHash,
|
||||
role
|
||||
) VALUES (
|
||||
p_email,
|
||||
p_passwordHash,
|
||||
p_role
|
||||
) RETURNING id INTO account_id;
|
||||
ELSE
|
||||
-- 0 means there is a duplicate account
|
||||
account_id = 0;
|
||||
END IF;
|
||||
|
||||
RETURN account_id;
|
||||
END;
|
||||
$BODY$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE OR REPLACE FUNCTION auth.bh_verify_account(
|
||||
p_verification_token VARCHAR(128))
|
||||
RETURNS INTEGER
|
||||
LANGUAGE plpgsql AS $BODY$
|
||||
DECLARE
|
||||
account_id INTEGER;
|
||||
verification_id INTEGER;
|
||||
BEGIN
|
||||
SELECT
|
||||
id, accountid INTO verification_id, account_id
|
||||
FROM auth.account_verification
|
||||
WHERE verificationtoken = p_verification_token;
|
||||
|
||||
IF account_id IS NULL OR account_id = 0 THEN
|
||||
-- 0 means there is a duplicate account
|
||||
account_id = 0;
|
||||
ELSE
|
||||
UPDATE auth.account SET verifiedTs=NOW() WHERE id = account_id;
|
||||
DELETE FROM auth.account_verification WHERE id = verification_id;
|
||||
END IF;
|
||||
|
||||
RETURN account_id;
|
||||
END;
|
||||
$BODY$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
DO
|
||||
$do$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT FROM pg_catalog.pg_roles
|
||||
WHERE rolname = 'auth-service') THEN
|
||||
|
||||
CREATE USER "auth-service" WITH PASSWORD 'auth-service';
|
||||
END IF;
|
||||
END
|
||||
$do$;
|
||||
-- +goose StatementEnd
|
||||
|
||||
GRANT CONNECT ON DATABASE bh to "auth-service";
|
||||
GRANT USAGE ON SCHEMA auth TO "auth-service";
|
||||
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA auth TO "auth-service";
|
||||
GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA auth TO "auth-service";
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- +goose Down
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
-- name: RegisterAccount :one
|
||||
SELECT auth.bh_register_account(
|
||||
sqlc.arg(email),
|
||||
sqlc.arg(passwordHash),
|
||||
sqlc.arg(role)
|
||||
);
|
||||
|
||||
-- name: GetAccountByEmailOrId :one
|
||||
SELECT
|
||||
id,
|
||||
createdTs,
|
||||
verifiedTs,
|
||||
email,
|
||||
role,
|
||||
enabled
|
||||
FROM auth.account
|
||||
WHERE
|
||||
email = sqlc.arg(email) OR id = sqlc.arg(accountId);
|
||||
|
||||
-- name: GetSessionAccount :one
|
||||
SELECT
|
||||
acc.id,
|
||||
acc.createdTs,
|
||||
acc.verifiedTs,
|
||||
acc.email,
|
||||
acc.role,
|
||||
acc.enabled
|
||||
FROM auth.account acc
|
||||
JOIN auth.sessions sess ON sess.accountId = acc.id
|
||||
WHERE sess.id = sqlc.arg(sessionId) AND acc.enabled = TRUE;
|
||||
|
||||
|
||||
-- name: VerifyAccount :one
|
||||
SELECT auth.bh_verify_account(
|
||||
sqlc.arg(token)
|
||||
);
|
||||
|
||||
|
||||
-- name: CreateSession :one
|
||||
INSERT INTO auth.sessions (
|
||||
accountId,
|
||||
createdTs
|
||||
) SELECT acc.id, NOW() FROM auth.account acc WHERE
|
||||
(acc.email = sqlc.arg(email) OR acc.id = sqlc.arg(accountId))
|
||||
AND acc.passwordHash = sqlc.arg(passwordHash)
|
||||
RETURNING *;
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
package data
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data/postgres"
|
||||
"github.com/jackc/pgx/v4"
|
||||
)
|
||||
|
||||
type (
|
||||
PGRunnerStorage struct {
|
||||
*postgres.Queries
|
||||
}
|
||||
|
||||
RegisterAccountInput struct {
|
||||
Email string
|
||||
PasswordHash string
|
||||
Role string
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrSessionNotFound = errors.New("session not found")
|
||||
ErrAccountNotFound = errors.New("account not found by the provided email or id")
|
||||
ErrCouldNotCreateSession = errors.New("could not create session")
|
||||
)
|
||||
|
||||
func (db *PGRunnerStorage) RegisterAccount(ctx context.Context, in RegisterAccountInput) (accountId int, err error) {
|
||||
var accId int32
|
||||
if accId, err = db.Queries.RegisterAccount(ctx, postgres.RegisterAccountParams{
|
||||
Email: in.Email,
|
||||
Passwordhash: in.PasswordHash,
|
||||
Role: in.Role,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not register a new account with DB: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
accountId = int(accId)
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
GetAccountInput struct {
|
||||
AccountID int
|
||||
Email string
|
||||
}
|
||||
|
||||
AccountResult struct {
|
||||
ID int `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Verified time.Time `json:"verified,omitempty"`
|
||||
Email string `json:"email"`
|
||||
PasswordHash string `json:"password_hash,omitempty"`
|
||||
Role string `json:"role"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
)
|
||||
|
||||
func (db *PGRunnerStorage) GetAccount(ctx context.Context, in GetAccountInput) (out AccountResult, err error) {
|
||||
var row postgres.GetAccountByEmailOrIdRow
|
||||
if row, err = db.Queries.GetAccountByEmailOrId(ctx, postgres.GetAccountByEmailOrIdParams{
|
||||
Email: in.Email,
|
||||
Accountid: int32(in.AccountID),
|
||||
}); errors.Is(err, pgx.ErrNoRows) {
|
||||
err = ErrAccountNotFound
|
||||
return
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("could not execute GetSessionAccount query: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = AccountResult{
|
||||
ID: int(row.ID),
|
||||
Email: row.Email,
|
||||
Role: row.Role,
|
||||
Created: row.Createdts,
|
||||
Verified: row.Verifiedts.Time,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (db *PGRunnerStorage) GetAccountBySession(ctx context.Context, sessionID int) (out AccountResult, err error) {
|
||||
var row postgres.GetSessionAccountRow
|
||||
if row, err = db.Queries.GetSessionAccount(ctx, int32(sessionID)); errors.Is(err, pgx.ErrNoRows) {
|
||||
err = ErrSessionNotFound
|
||||
return
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("could not execute GetSessionAccount query: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = AccountResult{
|
||||
ID: int(row.ID),
|
||||
Email: row.Email,
|
||||
Role: row.Role,
|
||||
Created: row.Createdts,
|
||||
Verified: row.Verifiedts.Time,
|
||||
Enabled: true,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
CreateSessionInput struct {
|
||||
Email string
|
||||
PasswordHash string
|
||||
}
|
||||
|
||||
Session struct {
|
||||
ID int
|
||||
AccountID int
|
||||
Created time.Time
|
||||
}
|
||||
)
|
||||
|
||||
func (db *PGRunnerStorage) CreateSession(ctx context.Context, in CreateSessionInput) (out Session, err error) {
|
||||
var session postgres.AuthSession
|
||||
if session, err = db.Queries.CreateSession(ctx, postgres.CreateSessionParams{
|
||||
Email: in.Email,
|
||||
Passwordhash: in.PasswordHash,
|
||||
}); errors.Is(err, pgx.ErrNoRows) {
|
||||
err = ErrCouldNotCreateSession
|
||||
return
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("could not execute query: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = Session{
|
||||
ID: int(session.ID),
|
||||
AccountID: int(session.Accountid),
|
||||
Created: session.Createdts,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type VerifyAccountInput struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
func (db *PGRunnerStorage) VerifyAccount(ctx context.Context, in VerifyAccountInput) (err error) {
|
||||
err = errors.New("Unimplemented")
|
||||
return
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
)
|
||||
|
||||
type (
|
||||
Domain struct {
|
||||
Storage
|
||||
PasswordHasher
|
||||
}
|
||||
|
||||
HashedPassword []byte
|
||||
|
||||
PasswordHasher interface {
|
||||
Hash(string) HashedPassword
|
||||
Compare(string, HashedPassword) bool
|
||||
}
|
||||
|
||||
Storage interface {
|
||||
RegisterAccount(context.Context, data.RegisterAccountInput) (int, error)
|
||||
GetAccountBySession(context.Context, int) (data.AccountResult, error)
|
||||
GetAccount(context.Context, data.GetAccountInput) (data.AccountResult, error)
|
||||
CreateSession(context.Context, data.CreateSessionInput) (data.Session, error)
|
||||
VerifyAccount(context.Context, data.VerifyAccountInput) error
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
CreateAccountCommand struct {
|
||||
Email string
|
||||
Password string
|
||||
Role Role
|
||||
}
|
||||
AccountCreated struct {
|
||||
Account
|
||||
}
|
||||
)
|
||||
|
||||
func (d *Domain) CreateAccount(ctx context.Context, in CreateAccountCommand) (out AccountCreated, err error) {
|
||||
if in.Email == "" {
|
||||
err = errors.New("email cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if in.Password == "" {
|
||||
err = errors.New("password cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
if in.Role == EmptyRole {
|
||||
in.Role = UserRole
|
||||
}
|
||||
|
||||
var accountID int
|
||||
if accountID, err = d.Storage.RegisterAccount(ctx, data.RegisterAccountInput{
|
||||
Email: in.Email,
|
||||
PasswordHash: in.Password,
|
||||
Role: in.Role.String(),
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not register account: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccount(ctx, data.GetAccountInput{
|
||||
Email: in.Email,
|
||||
AccountID: accountID,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not find account by ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = AccountCreated{
|
||||
Account: Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
PasswordHash: ar.PasswordHash,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
LoginCommand struct {
|
||||
Email string
|
||||
Password string
|
||||
}
|
||||
LoggedIn struct {
|
||||
Account
|
||||
SessionID int
|
||||
Created time.Time
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidLogin = errors.New("invalid credentials provided")
|
||||
ErrInvalidSession = errors.New("invalid session id provided")
|
||||
)
|
||||
|
||||
func (d *Domain) Login(ctx context.Context, in LoginCommand) (out LoggedIn, err error) {
|
||||
kernel.TraceLog.Printf("%q login attempt", in.Email)
|
||||
var sess data.Session
|
||||
if sess, err = d.Storage.CreateSession(ctx, data.CreateSessionInput{
|
||||
Email: in.Email,
|
||||
PasswordHash: in.Password,
|
||||
}); errors.Is(err, data.ErrCouldNotCreateSession) {
|
||||
err = ErrInvalidLogin
|
||||
return
|
||||
} else if err != nil {
|
||||
kernel.ErrorLog.Printf("Error creating session in storage for %q: %w", in.Email, err)
|
||||
err = ErrInvalidLogin
|
||||
return
|
||||
}
|
||||
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccount(ctx, data.GetAccountInput{
|
||||
AccountID: sess.AccountID,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("could not find account by ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = LoggedIn{
|
||||
Account: Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
},
|
||||
Created: sess.Created,
|
||||
SessionID: sess.ID,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
GetAccountCommand struct {
|
||||
SessionID int
|
||||
}
|
||||
)
|
||||
|
||||
func (d *Domain) GetAccount(ctx context.Context, in GetAccountCommand) (out Account, err error) {
|
||||
var ar data.AccountResult
|
||||
if ar, err = d.Storage.GetAccountBySession(ctx, in.SessionID); errors.Is(err, data.ErrSessionNotFound) {
|
||||
err = ErrInvalidSession
|
||||
return
|
||||
} else if err != nil {
|
||||
kernel.ErrorLog.Printf("Error getting account by session id: %w", err)
|
||||
err = fmt.Errorf("could not get account: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out = Account{
|
||||
ID: ar.ID,
|
||||
Created: ar.Created,
|
||||
Verified: ar.Verified,
|
||||
Email: ar.Email,
|
||||
Role: Role(ar.Role),
|
||||
Enabled: ar.Enabled,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type (
|
||||
VerifyAccountCommand struct{}
|
||||
AccountVerified struct{}
|
||||
)
|
||||
|
||||
func (d *Domain) VerifyAccount(ctx context.Context, in VerifyAccountCommand) (out AccountVerified, err error) {
|
||||
err = errors.New("Unimplemented")
|
||||
return
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data"
|
||||
)
|
||||
|
||||
func TestDomain_CreateAccount(t *testing.T) {
|
||||
SetupTest()
|
||||
|
||||
tests := map[string]struct {
|
||||
input CreateAccountCommand
|
||||
wantOut AccountCreated
|
||||
wantErr bool
|
||||
}{
|
||||
"new account": {
|
||||
input: CreateAccountCommand{
|
||||
Email: "test@example.com",
|
||||
Password: "password",
|
||||
},
|
||||
wantOut: AccountCreated{
|
||||
Account: Account{
|
||||
ID: 0,
|
||||
Email: "test@example.com",
|
||||
PasswordHash: "password",
|
||||
Enabled: true,
|
||||
Role: UserRole,
|
||||
},
|
||||
},
|
||||
},
|
||||
"no email": {
|
||||
input: CreateAccountCommand{
|
||||
Password: "password",
|
||||
Role: UserRole,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
"no password": {
|
||||
input: CreateAccountCommand{
|
||||
Email: "test@example.com",
|
||||
Role: UserRole,
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
"no inputs": {
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
c := ioc.Scope("CreateAccountTest")
|
||||
|
||||
Must(c.Provide(func(s Storage, ms *MockStorage) *Domain {
|
||||
return &Domain{Storage: s}
|
||||
}))
|
||||
|
||||
for name, v := range tests {
|
||||
params := v
|
||||
t.Run(name, func(t *testing.T) {
|
||||
Must(c.Invoke(func(sut *Domain, ms *MockStorage) {
|
||||
var a Account
|
||||
ms.RegisterAccountFunc = func(ctx context.Context, rai data.RegisterAccountInput) (int, error) {
|
||||
a = Account{
|
||||
Email: rai.Email,
|
||||
PasswordHash: rai.PasswordHash,
|
||||
Role: Role(rai.Role),
|
||||
Enabled: true,
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
ms.GetAccountFunc = func(ctx context.Context, gai data.GetAccountInput) (data.AccountResult, error) {
|
||||
if gai.Email != a.Email {
|
||||
return data.AccountResult{}, errors.New("error")
|
||||
}
|
||||
return data.AccountResult{
|
||||
Email: a.Email,
|
||||
PasswordHash: a.PasswordHash,
|
||||
Role: a.Role.String(),
|
||||
Enabled: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
out, err := sut.CreateAccount(context.Background(), params.input)
|
||||
if (err != nil) != params.wantErr {
|
||||
t.Errorf("Domain.CreateAccount() error = %v, wantErr %v", err, params.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(out, params.wantOut) {
|
||||
t.Errorf("Domain.CreateAccount():\n%+v\n, want:\n%+v", out, params.wantOut)
|
||||
}
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomain_Login(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
input LoginCommand
|
||||
wantOut LoggedIn
|
||||
wantErr bool
|
||||
}{
|
||||
"Login Valid User": {
|
||||
input: LoginCommand{
|
||||
Email: "test@example.com",
|
||||
Password: "password",
|
||||
},
|
||||
wantOut: LoggedIn{
|
||||
Account: Account{
|
||||
ID: 1,
|
||||
Email: "test@example.com",
|
||||
PasswordHash: "",
|
||||
Enabled: true,
|
||||
Role: UserRole,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
c := ioc.Scope("LoginTest")
|
||||
|
||||
Must(c.Provide(func(s Storage) *Domain {
|
||||
return &Domain{Storage: s}
|
||||
}))
|
||||
|
||||
for name, v := range tests {
|
||||
params := v
|
||||
t.Run(name, func(t *testing.T) {
|
||||
Must(c.Invoke(func(sut *Domain, ms *MockStorage) {
|
||||
ms.CreateSessionFunc = func(ctx context.Context, in data.CreateSessionInput) (data.Session, error) {
|
||||
if strings.EqualFold(in.Email, "test@example.com") {
|
||||
return data.Session{AccountID: 1}, nil
|
||||
}
|
||||
|
||||
return data.Session{}, data.ErrCouldNotCreateSession
|
||||
}
|
||||
|
||||
ms.GetAccountFunc = func(ctx context.Context, gai data.GetAccountInput) (data.AccountResult, error) {
|
||||
if strings.EqualFold(gai.Email, "test@example.com") || gai.AccountID == 1 {
|
||||
return data.AccountResult{
|
||||
ID: 1,
|
||||
Email: "test@example.com",
|
||||
Role: UserRole.String(),
|
||||
Enabled: true,
|
||||
}, nil
|
||||
}
|
||||
return data.AccountResult{}, data.ErrSessionNotFound
|
||||
}
|
||||
|
||||
out, err := sut.Login(context.Background(), params.input)
|
||||
if (err != nil) != params.wantErr {
|
||||
t.Errorf("Domain.Login() error = %v, wantErr %v", err, params.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(out, params.wantOut) {
|
||||
t.Errorf("Domain.Login() = %v, want %v", out, params.wantOut)
|
||||
}
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package domain
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
UserRole = Role("BIDDER")
|
||||
AdminRole = Role("ADMINISRATOR")
|
||||
AnonymousRole = Role("ANONYMOUS")
|
||||
EmptyRole = Role("")
|
||||
)
|
||||
|
||||
type Role string
|
||||
|
||||
func (r Role) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
ID int `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Verified time.Time `json:"verified,omitempty"`
|
||||
Email string `json:"email"`
|
||||
PasswordHash string `json:"password_hash,omitempty"`
|
||||
Role Role `json:"role"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID int
|
||||
AccountID int
|
||||
Created time.Time
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data"
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
|
||||
var ioc dig.Container
|
||||
|
||||
func SetupTest() {
|
||||
ioc = *dig.New()
|
||||
|
||||
if err := ioc.Provide(func() (Storage, *MockStorage) {
|
||||
ms := &MockStorage{}
|
||||
return ms, ms
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Must panics is err is not nil
|
||||
func Must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
type MockStorage struct {
|
||||
RegisterAccountFunc func(context.Context, data.RegisterAccountInput) (int, error)
|
||||
GetAccountFunc func(context.Context, data.GetAccountInput) (data.AccountResult, error)
|
||||
CreateSessionFunc func(context.Context, data.CreateSessionInput) (data.Session, error)
|
||||
}
|
||||
|
||||
// CreateSession implements Storage.
|
||||
func (m *MockStorage) CreateSession(ctx context.Context, in data.CreateSessionInput) (data.Session, error) {
|
||||
if m.CreateSessionFunc == nil {
|
||||
panic("CreateSessionFunc is unset")
|
||||
}
|
||||
return m.CreateSessionFunc(ctx, in)
|
||||
}
|
||||
|
||||
// GetAccount implements Storage.
|
||||
func (m *MockStorage) GetAccount(ctx context.Context, in data.GetAccountInput) (data.AccountResult, error) {
|
||||
if m.GetAccountFunc == nil {
|
||||
panic("GetAccountFunc is unset")
|
||||
}
|
||||
|
||||
return m.GetAccountFunc(ctx, in)
|
||||
}
|
||||
|
||||
// GetAccountBySession implements Storage.
|
||||
func (m *MockStorage) GetAccountBySession(ctx context.Context, in int) (data.AccountResult, error) {
|
||||
panic("GetAccountBySession not implemented")
|
||||
}
|
||||
|
||||
// RegisterAccount implements Storage.
|
||||
func (m *MockStorage) RegisterAccount(ctx context.Context, in data.RegisterAccountInput) (int, error) {
|
||||
if m.RegisterAccountFunc == nil {
|
||||
panic("RegisterAccountFunc is unset")
|
||||
}
|
||||
|
||||
return m.RegisterAccountFunc(ctx, in)
|
||||
}
|
||||
|
||||
// VerifyAccount implements Storage.
|
||||
func (*MockStorage) VerifyAccount(context.Context, data.VerifyAccountInput) error {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
api "git.vdhsn.com/barretthousen/barretthousen/src/auth/api/grpc"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/domain"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func NewAuthServer(d *domain.Domain) func(grpcServer grpc.ServiceRegistrar, endpoint string) {
|
||||
return func(grpcServer grpc.ServiceRegistrar, endpoint string) {
|
||||
api.RegisterAuthServer(grpcServer, &authHandler{domain: d})
|
||||
}
|
||||
}
|
||||
|
||||
type authHandler struct {
|
||||
api.UnimplementedAuthServer
|
||||
domain *domain.Domain
|
||||
}
|
||||
|
||||
func (a *authHandler) CreateAccount(ctx context.Context, in *api.CreateAccountInput) (*api.Account, error) {
|
||||
kernel.TraceLog.Printf("Attempting to create user: %q - %q", in.Email, in.Password)
|
||||
account, err := a.domain.CreateAccount(ctx, domain.CreateAccountCommand{
|
||||
Email: in.Email,
|
||||
Password: in.Password,
|
||||
Role: domain.Role(in.Role),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &api.Account{
|
||||
Id: int32(account.ID),
|
||||
Email: account.Email,
|
||||
Role: account.Role.String(),
|
||||
CreatedTs: timestamppb.New(account.Created),
|
||||
VerifiedTs: timestamppb.New(account.Verified),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *authHandler) Login(ctx context.Context, in *api.LoginInput) (out *api.LoginResult, err error) {
|
||||
var result domain.LoggedIn
|
||||
if result, err = a.domain.Login(ctx, domain.LoginCommand{
|
||||
Email: in.Email,
|
||||
Password: in.Password,
|
||||
}); errors.Is(err, domain.ErrInvalidLogin) {
|
||||
err = status.Errorf(codes.PermissionDenied, "Email or password invalid.")
|
||||
return
|
||||
} else if err != nil {
|
||||
err = fmt.Errorf("could not login: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = grpc.SetHeader(ctx, metadata.New(map[string]string{
|
||||
"bh-session-id": fmt.Sprintf("%d", result.SessionID),
|
||||
})); err != nil {
|
||||
err = status.Errorf(codes.Internal, "could not set header")
|
||||
return
|
||||
}
|
||||
|
||||
out = &api.LoginResult{
|
||||
SessionId: fmt.Sprintf("%d", result.SessionID),
|
||||
Account: &api.Account{
|
||||
Id: int32(result.ID),
|
||||
Email: result.Email,
|
||||
Role: result.Role.String(),
|
||||
CreatedTs: timestamppb.New(result.Created),
|
||||
VerifiedTs: nil,
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *authHandler) VerifyAccount(ctx context.Context, in *api.VerificationParameters) (*api.AccountVerifiedResult, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method VerifyAccount not implemented")
|
||||
}
|
||||
|
||||
func (a *authHandler) GetAccount(ctx context.Context, in *api.AccountFilter) (*api.Account, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAccount not implemented")
|
||||
}
|
||||
|
||||
func (a *authHandler) GetSession(ctx context.Context, in *api.SessionFilter) (out *api.Account, err error) {
|
||||
var result domain.Account
|
||||
if result, err = a.domain.GetAccount(ctx, domain.GetAccountCommand{
|
||||
SessionID: int(in.SessionId),
|
||||
}); err != nil {
|
||||
err = status.Error(codes.Unauthenticated, "forbidden")
|
||||
return
|
||||
}
|
||||
|
||||
out = &api.Account{
|
||||
Id: int32(result.ID),
|
||||
Email: result.Email,
|
||||
Role: result.Role.String(),
|
||||
CreatedTs: timestamppb.New(result.Created),
|
||||
VerifiedTs: nil,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
100
src/auth/main.go
100
src/auth/main.go
|
|
@ -1,100 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/data/postgres"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/auth/internal/domain"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
|
||||
type (
|
||||
authApp struct {
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" yaml-default:"0"`
|
||||
Port int `yaml:"port" `
|
||||
DB_Service kernel.PostgresConnection `yaml:"db_service"`
|
||||
DB_Migrate kernel.PostgresConnection `yaml:"db_migrate"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
migrate = flag.Bool("migrate", false, "migrates postgres db")
|
||||
client = flag.String("client", "", "Runs this service in client mode, to invoke sync job. Takes GRPC endpoint")
|
||||
target = flag.String("target", "", "To be used with client mode. The target to sync")
|
||||
|
||||
//go:embed internal/data/postgres/migrations/*.sql
|
||||
dbMigrateScript embed.FS
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
kernel.Run(context.Background(), &authApp{
|
||||
LogLevel: kernel.LevelTrace,
|
||||
Port: 5001,
|
||||
})
|
||||
}
|
||||
|
||||
func (app *authApp) Start(ctx context.Context) error {
|
||||
if *migrate {
|
||||
if err := kernel.MigrateDB(ctx, app.DB_Migrate, dbMigrateScript, "auth"); err != nil {
|
||||
return fmt.Errorf("could not execute db migration: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ioc := dig.New()
|
||||
var err error
|
||||
if err = ioc.Provide(func() kernel.PostgresConnection {
|
||||
return app.DB_Service
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func(pgCfg kernel.PostgresConnection) (*pgxpool.Pool, error) {
|
||||
return kernel.NewDBConnection(ctx, pgCfg)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func(pgConn *pgxpool.Pool) *postgres.Queries {
|
||||
return postgres.New(pgConn)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func(queries *postgres.Queries) domain.Storage {
|
||||
return &data.PGRunnerStorage{Queries: queries}
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func(rs domain.Storage) *domain.Domain {
|
||||
return &domain.Domain{
|
||||
Storage: rs,
|
||||
}
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioc.Invoke(func(d *domain.Domain) error {
|
||||
authService := internal.NewAuthServer(d)
|
||||
|
||||
if _, err := kernel.StartGRPCServer(ctx, app.Port, authService); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (app *authApp) OnStop(ctx context.Context) {
|
||||
}
|
||||
|
||||
func (app *authApp) GetLogLevel() kernel.LogLevel { return app.LogLevel }
|
||||
|
|
@ -1,7 +1,16 @@
|
|||
tests:
|
||||
- description: "Search for top"
|
||||
- description: "trigger scrape"
|
||||
request:
|
||||
path: "/api/v1/upcoming"
|
||||
method: "GET"
|
||||
path: "/v1/findNewUpcoming"
|
||||
method: "POST"
|
||||
headers:
|
||||
authorization: "token ${SECRET_AUTH_TOKEN}"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
- description: "get list of jobs"
|
||||
request:
|
||||
path: "/v1/jobs"
|
||||
headers:
|
||||
authorization: "token ${SECRET_AUTH_TOKEN}"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
|
|
|
|||
|
|
@ -1,64 +1,38 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
capi "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api/grpc"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
func NewCatalogServiceClient(conn grpc.ClientConnInterface) *CatalogServiceClient {
|
||||
return &CatalogServiceClient{
|
||||
CatalogClient: capi.NewCatalogClient(conn),
|
||||
}
|
||||
}
|
||||
|
||||
type CatalogServiceClient struct {
|
||||
capi.CatalogClient
|
||||
}
|
||||
|
||||
type Auction struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
SourceSiteURL string `json:"source_site_url,omitempty"`
|
||||
SourceSiteName string `json:"source_site_name,omitempty"`
|
||||
SourceURL string `json:"source_url,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
Province string `json:"province,omitempty"`
|
||||
ItemCount int `json:"itemCount,omitempty"`
|
||||
Start time.Time `json:"start,omitempty"`
|
||||
End time.Time `json:"end,omitempty"`
|
||||
Source SourceDetail `json:"source"`
|
||||
Seller SellerDetail `json:"seller"`
|
||||
Address AddressDetail `json:"address"`
|
||||
}
|
||||
|
||||
type AuctionCreatedEvent struct {
|
||||
Fingerprint string
|
||||
ID int
|
||||
Duplicate bool
|
||||
type SourceDetail struct {
|
||||
Name string `json:"name"`
|
||||
AuctionURL string `json:"auctionUrl"`
|
||||
SiteURL string `json:"siteURL"`
|
||||
}
|
||||
|
||||
func (css *CatalogServiceClient) UpdateUpcomingAuction(ctx context.Context, a Auction) (AuctionCreatedEvent, error) {
|
||||
ac, err := css.ImportAuction(ctx, &capi.ImportAuctionMessage{
|
||||
Items: int32(a.ItemCount),
|
||||
Start: timestamppb.New(a.Start),
|
||||
End: timestamppb.New(a.End),
|
||||
Title: a.Title,
|
||||
Description: a.Description,
|
||||
SourceSiteURL: a.SourceSiteURL,
|
||||
SourceSiteName: a.SourceSiteName,
|
||||
SourceURL: a.SourceURL,
|
||||
Country: a.Country,
|
||||
Province: a.Province,
|
||||
})
|
||||
if err != nil {
|
||||
return AuctionCreatedEvent{}, err
|
||||
}
|
||||
|
||||
return AuctionCreatedEvent{
|
||||
Fingerprint: ac.Auction.Fingerprint,
|
||||
ID: int(ac.Auction.Id),
|
||||
Duplicate: ac.Duplicate,
|
||||
}, nil
|
||||
type SellerDetail struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SiteURL string `json:"siteUrl"`
|
||||
}
|
||||
|
||||
type AddressDetail struct {
|
||||
CountryCode string `json:"country"`
|
||||
Lat float64 `json:"lat"`
|
||||
Long float64 `json:"lng"`
|
||||
State string `json:"state"`
|
||||
City string `json:"city"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ service Catalog {
|
|||
};
|
||||
}
|
||||
|
||||
rpc ImportAuction(ImportAuctionMessage) returns (AuctionCreated) {
|
||||
}
|
||||
// rpc ImportAuction(ImportAuctionMessage) returns (AuctionCreated) {
|
||||
// }
|
||||
}
|
||||
|
||||
message AuctionSearchCriteria {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
log_level: ERROR
|
||||
|
||||
service: {}
|
||||
|
|
@ -18,7 +18,7 @@ require (
|
|||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/pressly/goose/v3 v3.11.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
|
||||
|
|
|
|||
|
|
@ -180,8 +180,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
package kafka
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
kafka "github.com/segmentio/kafka-go"
|
||||
)
|
||||
|
||||
type kafkaConsumer struct {
|
||||
*kafka.Conn
|
||||
}
|
||||
|
||||
func (c *kafkaConsumer) Close() error {
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
func (c *kafkaConsumer) ConsumeAsync(ctx context.Context, output chan<- []byte) {
|
||||
for {
|
||||
|
||||
batch := c.ReadBatch(1024, 1024*50)
|
||||
|
||||
for {
|
||||
msg, err := batch.ReadMessage()
|
||||
if err != nil && !errors.Is(err, io.EOF) || len(msg.Value) == 0 {
|
||||
break
|
||||
}
|
||||
kernel.TraceLog.Printf("header: %+v, value: %+v", msg.Headers, msg.Value)
|
||||
|
||||
select {
|
||||
case output <- msg.Value:
|
||||
case <-ctx.Done():
|
||||
batch.Close()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
batch.Close()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewConsumer(topic string) (*kafkaConsumer, error) {
|
||||
conn, err := kafka.DialLeader(context.Background(), "tcp", "kafka:9092", topic, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &kafkaConsumer{
|
||||
Conn: conn,
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
api "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal/domain"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
)
|
||||
|
||||
type KafkaConsumer interface {
|
||||
io.Closer
|
||||
ConsumeAsync(context.Context, chan<- []byte)
|
||||
}
|
||||
|
||||
type AuctionImporter interface {
|
||||
ImportAuction(context.Context, domain.ImportAuctionMessage) (domain.AuctionCreated, error)
|
||||
}
|
||||
|
||||
func RunIndexer(ctx context.Context, c KafkaConsumer, importer AuctionImporter) {
|
||||
defer c.Close()
|
||||
|
||||
msgs := make(chan []byte, 64)
|
||||
go c.ConsumeAsync(ctx, msgs)
|
||||
|
||||
for msg := range msgs {
|
||||
var auction api.Auction
|
||||
if err := json.Unmarshal(msg, &auction); err != nil {
|
||||
kernel.TraceLog.Printf("could not ingest: %w", err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err := importer.ImportAuction(ctx, domain.ImportAuctionMessage{
|
||||
Auction: domain.Auction{
|
||||
ItemCount: auction.ItemCount,
|
||||
Start: auction.Start,
|
||||
End: auction.End,
|
||||
Title: auction.Title,
|
||||
Description: auction.Description,
|
||||
SourceSiteURL: auction.Source.SiteURL,
|
||||
SourceSiteName: auction.Source.Name,
|
||||
SourceURL: auction.Source.AuctionURL,
|
||||
Country: auction.Address.CountryCode,
|
||||
Province: auction.Address.State,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
kernel.ErrorLog.Printf("could not import auction: %w", err)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal/data"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal/data/kafka"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal/data/postgres"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/catalog/internal/domain"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
|
|
@ -17,10 +18,10 @@ import (
|
|||
|
||||
type (
|
||||
catalogApp struct {
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" yaml-default:"0"`
|
||||
Port int `yaml:"port"`
|
||||
DB_Service kernel.PostgresConnection `yaml:"db_service"`
|
||||
DB_Migrate kernel.PostgresConnection `yaml:"db_migrate"`
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" env:"BH_LOG_LEVEL" env-default:"0" yaml-default:"0"`
|
||||
Port int `yaml:"port" env:"catalog_PORT"`
|
||||
DB_Service kernel.PostgresConnection `yaml:"db_service" env:"catalog_DB_SERVICE"`
|
||||
DB_Migrate kernel.PostgresConnection `yaml:"db_migrate" env:"catalog_DB_MIGRATE"`
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -80,7 +81,15 @@ func (app *catalogApp) Start(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return ioc.Invoke(func(d *domain.Usecase) error {
|
||||
if err = ioc.Provide(func() (internal.KafkaConsumer, error) {
|
||||
return kafka.NewConsumer("runner.sync_results")
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioc.Invoke(func(d *domain.Usecase, consumer internal.KafkaConsumer) error {
|
||||
go internal.RunIndexer(ctx, consumer, d)
|
||||
|
||||
catalogService := internal.NewCatalogServer(d)
|
||||
|
||||
if _, err := kernel.StartGRPCServer(ctx, app.Port, catalogService); err != nil {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ go 1.19
|
|||
require (
|
||||
github.com/jackc/pgx/v4 v4.18.1
|
||||
go.uber.org/automaxprocs v1.5.2
|
||||
golang.org/x/sync v0.2.0
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
|
||||
google.golang.org/grpc v1.55.0
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -175,8 +175,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ func Run(parent context.Context, app App) {
|
|||
return
|
||||
}
|
||||
|
||||
TraceLog.Printf("Using config: %+v", app)
|
||||
|
||||
if err := app.Start(ctx); err != nil {
|
||||
ErrorLog.Println(err)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@ import (
|
|||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/reflection"
|
||||
)
|
||||
|
||||
type ServerBuilder func(grpc.ServiceRegistrar, string)
|
||||
|
|
@ -40,8 +38,6 @@ func StartGRPCServer(ctx context.Context, port int, sb ServerBuilder, opts ...gr
|
|||
|
||||
grpcServerInstance = grpc.NewServer(opts...)
|
||||
|
||||
reflection.Register(grpcServerInstance)
|
||||
|
||||
sb(grpcServerInstance, endpoint)
|
||||
|
||||
if err = grpcServerInstance.Serve(listener); err != nil {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,9 @@ module git.vdhsn.com/barretthousen/barretthousen/src/proxy-admin
|
|||
go 1.19
|
||||
|
||||
require (
|
||||
git.vdhsn.com/barretthousen/barretthousen/src/auth v1.0.0
|
||||
git.vdhsn.com/barretthousen/barretthousen/src/lib v1.0.0
|
||||
git.vdhsn.com/barretthousen/barretthousen/src/runner v1.0.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2
|
||||
go.uber.org/dig v1.16.1
|
||||
google.golang.org/grpc v1.55.0
|
||||
)
|
||||
|
||||
|
|
@ -41,5 +39,3 @@ require (
|
|||
replace git.vdhsn.com/barretthousen/barretthousen/src/lib v1.0.0 => ../lib
|
||||
|
||||
replace git.vdhsn.com/barretthousen/barretthousen/src/runner v1.0.0 => ../runner
|
||||
|
||||
replace git.vdhsn.com/barretthousen/barretthousen/src/auth v1.0.0 => ../auth
|
||||
|
|
|
|||
|
|
@ -143,7 +143,6 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
|||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
|
||||
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||
go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
|
|
|
|||
|
|
@ -4,58 +4,27 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
authApi "git.vdhsn.com/barretthousen/barretthousen/src/auth/api"
|
||||
aapi "git.vdhsn.com/barretthousen/barretthousen/src/auth/api/grpc"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
api "git.vdhsn.com/barretthousen/barretthousen/src/runner/api/grpc"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"go.uber.org/dig"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
)
|
||||
|
||||
type ProxyAdminApp struct {
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" yaml-default:"0"`
|
||||
Port int `yaml:"port" `
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" env:"BH_LOG_LEVEL" env-default:"0" yaml-default:"0"`
|
||||
Port int `yaml:"port" env:"PROXY_ADMIN_PORT"`
|
||||
Endpoints struct {
|
||||
Runner string `yaml:"runner" `
|
||||
Auth string `yaml:"auth"`
|
||||
} `yaml:"endpoints"`
|
||||
}
|
||||
|
||||
type AuthService interface {
|
||||
CheckSession(context.Context, authApi.CheckSessionParams) (authApi.Account, error)
|
||||
Runner string `yaml:"runner" env:"RUNNER_ENDPOINT"`
|
||||
} `yaml:"endpoints" env:"PROXY_ADMIN_SERVICES"`
|
||||
}
|
||||
|
||||
func (app *ProxyAdminApp) Start(ctx context.Context) error {
|
||||
ioc := dig.New()
|
||||
|
||||
var err error
|
||||
if err = ioc.Provide(func() *runtime.ServeMux {
|
||||
return runtime.NewServeMux()
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func() (grpc.ClientConnInterface, error) {
|
||||
return kernel.DialGRPC(app.Endpoints.Auth)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Provide(func(conn grpc.ClientConnInterface) AuthService {
|
||||
return authApi.NewAuthServiceClient(conn)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = ioc.Invoke(func(grpcMux *runtime.ServeMux, authClient AuthService) error {
|
||||
// TODO: refactor into kernel package
|
||||
if err := api.RegisterRunnerHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Runner, []grpc.DialOption{
|
||||
grpcMux := runtime.NewServeMux()
|
||||
err := api.RegisterRunnerHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Runner, []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithConnectParams(grpc.ConnectParams{
|
||||
Backoff: backoff.Config{
|
||||
|
|
@ -63,56 +32,18 @@ func (app *ProxyAdminApp) Start(ctx context.Context) error {
|
|||
},
|
||||
MinConnectTimeout: time.Second,
|
||||
}),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: refactor into kernel package
|
||||
if err := aapi.RegisterAuthHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Auth, []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithConnectParams(grpc.ConnectParams{
|
||||
Backoff: backoff.Config{
|
||||
MaxDelay: time.Second * 3,
|
||||
},
|
||||
MinConnectTimeout: time.Second,
|
||||
}),
|
||||
}); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kernel.TraceLog.Printf("%+v", app)
|
||||
|
||||
httpServer := &http.Server{
|
||||
Addr: fmt.Sprintf("0.0.0.0:%d", app.Port),
|
||||
ReadHeaderTimeout: time.Second,
|
||||
Handler: http.StripPrefix("/api", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
kernel.TraceLog.Printf("{ \"Client\": \"%s\", \"Path\":\"%s\", \"User-Agent\":\"%s\", \"Host\":\"%s\", \"Origin\":\"%s\"} ", r.RemoteAddr, r.URL, r.UserAgent(), r.Host, r.Header.Get("Origin"))
|
||||
|
||||
// TODO: move to a middleware package
|
||||
if strings.HasPrefix(r.Host, "proxy-") {
|
||||
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
|
||||
}
|
||||
|
||||
// TODO: move to a middleware package
|
||||
if !(strings.HasSuffix(r.URL.Path, "user") && r.Method == http.MethodPost) {
|
||||
sessIdStr := r.Header.Get("bh-session-id")
|
||||
kernel.TraceLog.Printf("session %s", sessIdStr)
|
||||
account, err := authClient.CheckSession(r.Context(), authApi.CheckSessionParams{
|
||||
SessionID: sessIdStr,
|
||||
})
|
||||
if err != nil {
|
||||
kernel.ErrorLog.Printf("error calling auth service: %v", err)
|
||||
http.Error(w, "must be logged in as admin", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
kernel.TraceLog.Printf("{ \"session-id\":\"%s\", \"email\":\"%s\", \"accountId\":\"%d\", \"role\":\"%s\"}", sessIdStr, account.Email, account.ID, account.Role)
|
||||
if account.Role != "ADMINISTRATOR" {
|
||||
http.Error(w, "must be administrator", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
kernel.TraceLog.Printf("{ \"Client\": \"%s\", \"Path\":\"%s\"} ", r.RemoteAddr, r.URL.Path)
|
||||
grpcMux.ServeHTTP(w, r)
|
||||
})),
|
||||
}
|
||||
|
|
@ -120,11 +51,6 @@ func (app *ProxyAdminApp) Start(ctx context.Context) error {
|
|||
kernel.InfoLog.Printf("Starting HTTP proxy @ %q", httpServer.Addr)
|
||||
|
||||
return httpServer.ListenAndServe()
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *ProxyAdminApp) OnStop(ctx context.Context) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
module git.vdhsn.com/barretthousen/barretthousen/src/proxy-web
|
||||
module git.vdhsn.com/barretthousen/barretthousen/src/proxy-client
|
||||
|
||||
go 1.19
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ require (
|
|||
go.uber.org/automaxprocs v1.5.2 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
|
|
@ -39,5 +39,3 @@ require (
|
|||
replace git.vdhsn.com/barretthousen/barretthousen/src/lib v1.0.0 => ../lib
|
||||
|
||||
replace git.vdhsn.com/barretthousen/barretthousen/src/catalog v1.0.0 => ../catalog
|
||||
|
||||
replace git.vdhsn.com/barretthousen/barretthousen/src/auth v1.0.0 => ../auth
|
||||
|
|
@ -178,8 +178,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
|
@ -4,10 +4,8 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
auth_api "git.vdhsn.com/barretthousen/barretthousen/src/auth/api/grpc"
|
||||
api "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api/grpc"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
|
|
@ -17,17 +15,17 @@ import (
|
|||
)
|
||||
|
||||
type ProxyClientApp struct {
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" yaml-default:"0"`
|
||||
Port int `yaml:"port"`
|
||||
LogLevel kernel.LogLevel `yaml:"log_level" env:"BH_LOG_LEVEL" env-default:"0" yaml-default:"0"`
|
||||
Port int `yaml:"port" env:"PROXY_CLIENT_PORT"`
|
||||
AccessControlAllowOrigin string `yaml:"access_control_allow_origin", env:"PROXY_CLIENT_CORS_ORIGIN`
|
||||
Endpoints struct {
|
||||
Catalog string `yaml:"catalog"`
|
||||
Auth string `yaml:"auth"`
|
||||
Catalog string `yaml:"catalog" env:"CATALOG_ENDPOINT"`
|
||||
} `yaml:"endpoints" env:"PROXY_CLIENT_SERVICES"`
|
||||
}
|
||||
|
||||
func (app *ProxyClientApp) Start(ctx context.Context) error {
|
||||
grpcMux := runtime.NewServeMux()
|
||||
grpcOpts := []grpc.DialOption{
|
||||
err := api.RegisterCatalogHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Catalog, []grpc.DialOption{
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
grpc.WithConnectParams(grpc.ConnectParams{
|
||||
Backoff: backoff.Config{
|
||||
|
|
@ -35,13 +33,8 @@ func (app *ProxyClientApp) Start(ctx context.Context) error {
|
|||
},
|
||||
MinConnectTimeout: time.Second,
|
||||
}),
|
||||
}
|
||||
|
||||
if err := api.RegisterCatalogHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Catalog, grpcOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := auth_api.RegisterAuthHandlerFromEndpoint(ctx, grpcMux, app.Endpoints.Auth, grpcOpts); err != nil {
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -51,12 +44,9 @@ func (app *ProxyClientApp) Start(ctx context.Context) error {
|
|||
Addr: fmt.Sprintf("0.0.0.0:%d", app.Port),
|
||||
ReadHeaderTimeout: time.Second,
|
||||
Handler: http.StripPrefix("/api", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
kernel.TraceLog.Printf("{ \"Client\": \"%s\", \"Path\":\"%s\", \"User-Agent\":\"%s\", \"Host\":\"%s\", \"Origin\":\"%s\"} ", r.RemoteAddr, r.URL, r.UserAgent(), r.Host, r.Header.Get("Origin"))
|
||||
|
||||
if strings.HasPrefix(r.Host, "proxy-") {
|
||||
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
|
||||
}
|
||||
|
||||
kernel.TraceLog.Printf("{ \"Client\": \"%s\", \"Path\":\"%s\", \"User-Agent\":\"%s\" } ", r.RemoteAddr, r.URL, r.UserAgent())
|
||||
// TODO: pull the allowed origin host names from the config file
|
||||
w.Header().Set("Access-Control-Allow-Origin", app.AccessControlAllowOrigin)
|
||||
grpcMux.ServeHTTP(w, r)
|
||||
})),
|
||||
}
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
tests:
|
||||
- description: "trigger sync"
|
||||
- description: "trigger scrape"
|
||||
request:
|
||||
path: "/v1/sync"
|
||||
method: "PUT"
|
||||
path: "/v1/findNewUpcoming"
|
||||
method: "POST"
|
||||
headers:
|
||||
authorization: "token ${SECRET_AUTH_TOKEN}"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
- description: "get list of jobs"
|
||||
request:
|
||||
path: "/v1/sync?page=1&limit=6"
|
||||
path: "/v1/jobs"
|
||||
headers:
|
||||
authorization: "token ${SECRET_AUTH_TOKEN}"
|
||||
response:
|
||||
statusCodes: [200]
|
||||
|
|
|
|||
|
|
@ -37,14 +37,11 @@ message SyncStatus {
|
|||
|
||||
message StatusFilter {
|
||||
int32 page = 1;
|
||||
int32 limit = 2;
|
||||
int32 id = 2;
|
||||
}
|
||||
|
||||
message SyncStatusList {
|
||||
repeated SyncStatus active = 1;
|
||||
repeated SyncStatus complete = 2;
|
||||
int32 page = 3;
|
||||
int32 total = 4;
|
||||
int32 activeTotal = 5;
|
||||
int32 completeTotal = 6;
|
||||
repeated SyncStatus results = 1;
|
||||
int32 page = 2;
|
||||
int32 total = 3;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
log_level: 2
|
||||
port: 5001
|
||||
|
||||
kafka_bootstrap_servers:
|
||||
- kafka
|
||||
|
||||
db_service:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
host: bh-db
|
||||
name: bh
|
||||
user: runner-service
|
||||
password: runner-service
|
||||
|
||||
db_migrate:
|
||||
scheme: postgres
|
||||
port: 5432
|
||||
host: bh-db
|
||||
name: bh
|
||||
user: postgres
|
||||
password: bh-admin
|
||||
|
|
@ -18,6 +18,10 @@ require (
|
|||
github.com/ilyakaznacheev/cleanenv v1.4.2 // indirect
|
||||
github.com/jackc/puddle v1.3.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/klauspost/compress v1.16.4 // indirect
|
||||
github.com/moby/patternmatcher v0.5.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
||||
github.com/pressly/goose/v3 v3.11.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
|
|
@ -34,6 +38,7 @@ require (
|
|||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgtype v1.14.0 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.1
|
||||
github.com/segmentio/kafka-go v0.4.40
|
||||
go.uber.org/automaxprocs v1.5.2 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
|
|
|
|||
2352
src/runner/go.sum
2352
src/runner/go.sum
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,55 @@
|
|||
package kafka
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
kafka "github.com/segmentio/kafka-go"
|
||||
)
|
||||
|
||||
type kafkaProducer struct {
|
||||
*kafka.Conn
|
||||
}
|
||||
|
||||
func (c *kafkaProducer) Close() error {
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
func (c *kafkaProducer) SendMessageJSON(headers map[string]string, msg interface{}) (err error) {
|
||||
var data []byte
|
||||
if data, err = json.Marshal(msg); err != nil {
|
||||
err = fmt.Errorf("could not marshal message into JSON: %w", err)
|
||||
return
|
||||
}
|
||||
h := []kafka.Header{}
|
||||
|
||||
for k, v := range headers {
|
||||
h = append(h, kafka.Header{
|
||||
Key: k,
|
||||
Value: []byte(v),
|
||||
})
|
||||
}
|
||||
|
||||
if _, err = c.WriteMessages(kafka.Message{
|
||||
Time: time.Now().UTC(),
|
||||
Headers: h,
|
||||
Value: data,
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func NewProducer(topic string) (*kafkaProducer, error) {
|
||||
conn, err := kafka.DialLeader(context.Background(), "tcp", "kafka:9092", topic, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &kafkaProducer{
|
||||
Conn: conn,
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
-- name: GetCompletedJobs :many
|
||||
-- name: GetJobs :many
|
||||
SELECT id,
|
||||
startedTs,
|
||||
completedTs,
|
||||
|
|
@ -6,31 +6,7 @@ SELECT id,
|
|||
auctionsFound,
|
||||
errors
|
||||
FROM runner.scrapejob
|
||||
WHERE completedts is not null OR NOW() >= startedts + (30 ||' minutes')::interval
|
||||
ORDER BY startedTs DESC
|
||||
OFFSET (sqlc.arg(page)::INTEGER * sqlc.arg(pageSize)::INTEGER)
|
||||
LIMIT sqlc.arg(pageSize)::INTEGER;
|
||||
|
||||
-- name: GetActiveJobs :many
|
||||
SELECT id,
|
||||
startedTs,
|
||||
completedTs,
|
||||
targetSiteName,
|
||||
auctionsFound,
|
||||
errors
|
||||
FROM runner.scrapejob
|
||||
WHERE completedTs is null AND NOW() < startedTs + (30 ||' minutes')::interval
|
||||
ORDER BY startedTs DESC
|
||||
OFFSET (sqlc.arg(page)::INTEGER * sqlc.arg(pageSize)::INTEGER)
|
||||
LIMIT sqlc.arg(pageSize)::INTEGER;
|
||||
|
||||
-- name: GetJobCounts :one
|
||||
SELECT COUNT(*) AS total,
|
||||
(SELECT COUNT(*) FROM runner.scrapejob
|
||||
WHERE completedts is not null OR NOW() >= startedts + (30 ||' minutes')::interval) AS completed,
|
||||
(SELECT COUNT(*) FROM runner.scrapejob
|
||||
WHERE completedts is null AND NOW() < startedts + (30 ||' minutes')::interval) AS active
|
||||
FROM runner.scrapejob;
|
||||
ORDER BY startedTs DESC;
|
||||
|
||||
-- name: GetJobByID :one
|
||||
SELECT id,
|
||||
|
|
|
|||
|
|
@ -64,54 +64,22 @@ func (db *PGRunnerStorage) CompleteScrapeJob(ctx context.Context, ID int, status
|
|||
return
|
||||
}
|
||||
|
||||
func (db *PGRunnerStorage) GetJobs(ctx context.Context, page int32, limit int32) (out domain.GetJobsResult, err error) {
|
||||
var completeJobs []postgres.RunnerScrapejob
|
||||
if completeJobs, err = db.Queries.GetCompletedJobs(ctx, postgres.GetCompletedJobsParams{
|
||||
Page: page,
|
||||
Pagesize: limit,
|
||||
}); err != nil {
|
||||
func (db *PGRunnerStorage) GetJobs(ctx context.Context) (results []domain.ScrapeJob, err error) {
|
||||
var jobs []postgres.RunnerScrapejob
|
||||
if jobs, err = db.Queries.GetJobs(ctx); err != nil {
|
||||
err = fmt.Errorf("Couldn't get jobs from DB: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
var activeJobs []postgres.RunnerScrapejob
|
||||
if activeJobs, err = db.Queries.GetActiveJobs(ctx, postgres.GetActiveJobsParams{
|
||||
Page: 0,
|
||||
Pagesize: 64,
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("Couldn't get jobs from DB: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
var jobCounts postgres.GetJobCountsRow
|
||||
if jobCounts, err = db.Queries.GetJobCounts(ctx); err != nil {
|
||||
err = fmt.Errorf("couldn't get total job count: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
out.Total = int(jobCounts.Total)
|
||||
out.ActiveTotal = int(jobCounts.Active)
|
||||
out.CompletedTotal = int(jobCounts.Completed)
|
||||
out.Active = mapScrapeJob(activeJobs)
|
||||
out.Complete = mapScrapeJob(completeJobs)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func mapScrapeJob(jobs []postgres.RunnerScrapejob) (result []domain.ScrapeJob) {
|
||||
result = make([]domain.ScrapeJob, len(jobs))
|
||||
for i, j := range jobs {
|
||||
result[i] = domain.ScrapeJob{
|
||||
for _, j := range jobs {
|
||||
results = append(results, domain.ScrapeJob{
|
||||
ID: int(j.ID),
|
||||
Started: j.Startedts,
|
||||
Completed: j.Completedts.Time,
|
||||
TargetSite: j.Targetsitename,
|
||||
AuctionsFound: int(j.Auctionsfound),
|
||||
Errors: j.Errors,
|
||||
}
|
||||
|
||||
if j.Completedts.Valid {
|
||||
result[i].Completed = j.Completedts.Time
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
package catawiki
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
catalog "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/lib/kernel"
|
||||
"git.vdhsn.com/barretthousen/barretthousen/src/runner/internal/domain"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func init() {
|
||||
kernel.TraceLog.Println("Registering AuctionFinder catawiki")
|
||||
domain.RegisterAuctionFinder(
|
||||
CatawikiAuctionFinder("catawiki"),
|
||||
)
|
||||
}
|
||||
|
||||
type CatawikiAuctionFinder string
|
||||
|
||||
func (cw CatawikiAuctionFinder) String() string {
|
||||
return string(cw)
|
||||
}
|
||||
|
||||
func (cw CatawikiAuctionFinder) Find(ctx context.Context, limit int, results chan<- catalog.Auction) (err error) {
|
||||
defer close(results)
|
||||
|
||||
pageSize := 50
|
||||
|
||||
if limit > 2500 {
|
||||
limit = 2500
|
||||
}
|
||||
|
||||
if limit <= 0 {
|
||||
limit = 2500
|
||||
}
|
||||
|
||||
errg, errgCtx := errgroup.WithContext(ctx)
|
||||
errg.SetLimit(5)
|
||||
|
||||
kernel.TraceLog.Printf("[Catawiki] fetching %d pages or up to %d results in %d batches", limit/pageSize, limit, pageSize)
|
||||
for p := 1; p <= limit/pageSize; p++ {
|
||||
pageIdx := p
|
||||
errg.Go(func() error {
|
||||
auctionR, err := GetUpcomingAuctions(errgCtx, limit, pageIdx)
|
||||
if errors.Is(err, ErrNoResults) {
|
||||
kernel.TraceLog.Println("no more results from catawiki api")
|
||||
return err
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, r := range auctionR {
|
||||
select {
|
||||
case <-errgCtx.Done():
|
||||
kernel.TraceLog.Println("[Catawiki] group context exited early")
|
||||
return nil
|
||||
default:
|
||||
results <- r
|
||||
kernel.TraceLog.Printf("[Catawiki]: %+v", r)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err = errg.Wait(); err != nil {
|
||||
kernel.ErrorLog.Printf("[Catawiki] could not get results f: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var ErrNoResults = errors.New("No results found")
|
||||
|
||||
func GetUpcomingAuctions(ctx context.Context, limit int, page int) (results []catalog.Auction, err error) {
|
||||
if limit <= 25 {
|
||||
limit = 25
|
||||
} else if limit >= 50 {
|
||||
limit = 50
|
||||
}
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("https://www.catawiki.com/buyer/api/v1/auctions?locale=en&=published_at_desc&per_page=%d&page=%d", limit, page)
|
||||
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("Accept-Language", "en-US,en;q=0.5")
|
||||
req.Header.Add("User-Agent", "barretthousen.com Auction Search Engine")
|
||||
|
||||
kernel.TraceLog.Printf("[Catawiki] Loading page %d of %d results", page, limit)
|
||||
var res *http.Response
|
||||
if res, err = http.DefaultClient.Do(req); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
err = fmt.Errorf("bad response code: %d", res.StatusCode)
|
||||
return
|
||||
}
|
||||
|
||||
type Payload struct {
|
||||
Auctions []struct {
|
||||
ID int `json:"id"`
|
||||
StartAt string `json:"start_at"`
|
||||
CloseAt string `json:"close_at"`
|
||||
LotCount int `json:"lot_count"`
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
Status string `json:"status"`
|
||||
Sellers []struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
} `json:"sellers"`
|
||||
} `json:"auctions"`
|
||||
}
|
||||
|
||||
var p Payload
|
||||
if err = json.NewDecoder(res.Body).Decode(&p); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(p.Auctions) <= 0 {
|
||||
err = ErrNoResults
|
||||
return
|
||||
}
|
||||
|
||||
results = make([]catalog.Auction, len(p.Auctions))
|
||||
for idx, auction := range p.Auctions {
|
||||
results[idx] = catalog.Auction{
|
||||
Title: auction.Title,
|
||||
Description: "",
|
||||
SourceSiteURL: "https://www.catawiki.com",
|
||||
SourceSiteName: "CataWiki",
|
||||
SourceURL: auction.URL,
|
||||
Country: "",
|
||||
Province: "",
|
||||
ItemCount: auction.LotCount,
|
||||
}
|
||||
|
||||
results[idx].Start, _ = time.Parse(time.RFC3339, auction.StartAt)
|
||||
results[idx].End, _ = time.Parse(time.RFC3339, auction.CloseAt)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
package catawiki
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
catalog "git.vdhsn.com/barretthousen/barretthousen/src/catalog/api"
|
||||
)
|
||||
|
||||
func TestGetUpcomingAuctions(t *testing.T) {
|
||||
type args struct {
|
||||
limit int
|
||||
page int
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantResults []catalog.Auction
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "1 Page, 25 Results",
|
||||
args: args{
|
||||
limit: 25,
|
||||
page: 1,
|
||||
},
|
||||
wantResults: make([]catalog.Auction, 25),
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotResults, err := GetUpcomingAuctions(context.TODO(), tt.args.limit, tt.args.page)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetUpcomingAuctions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotResults, tt.wantResults) {
|
||||
t.Errorf("GetUpcomingAuctions() = %v, want %v", gotResults, tt.wantResults)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -71,13 +71,15 @@ type GetUpcomingSaleIDsInput struct {
|
|||
}
|
||||
|
||||
func LAGetUpcomingSaleIDs(ctx context.Context, in GetUpcomingSaleIDsInput) (ids LACatalogIDs, total int, err error) {
|
||||
if in.Limit == 0 {
|
||||
in.Limit = 128
|
||||
}
|
||||
|
||||
req, _ := http.NewRequestWithContext(
|
||||
ctx,
|
||||
http.MethodGet,
|
||||
fmt.Sprintf(
|
||||
"https://search-party-prod.liveauctioneers.com/search/catalogsearch?client_version=5.0&client=web&offset=300&sort=saleStart&page=%d&pageSize=%d&",
|
||||
"https://search-party-prod.liveauctioneers.com/search/catalogsearch?page=%d&sort=saleStart&pageSize=%d",
|
||||
in.Page,
|
||||
in.Limit,
|
||||
),
|
||||
|
|
@ -199,14 +201,24 @@ func LAGetSaleInfo(ctx context.Context, catIDs LACatalogIDs) (results []catalog.
|
|||
results[idx] = catalog.Auction{
|
||||
Title: c.Title,
|
||||
Description: c.Description,
|
||||
SourceSiteURL: "https://www.liveauctioneers.com",
|
||||
SourceSiteName: "Live Auctioneers",
|
||||
SourceURL: fmt.Sprintf("https://www.liveauctioneers.com/catalog/%d", c.ID),
|
||||
Start: time.Unix(c.SaleStartTS, 0),
|
||||
End: time.Unix(c.SaleStartTS, 0).Add(time.Hour * 8),
|
||||
ItemCount: c.ItemCount,
|
||||
Country: c.Address.CountryCode,
|
||||
Province: c.Address.City,
|
||||
Source: catalog.SourceDetail{
|
||||
SiteURL: "https://www.liveauctioneers.com",
|
||||
Name: "Live Auctioneers",
|
||||
AuctionURL: fmt.Sprintf("https://www.liveauctioneers.com/catalog/%d", c.ID),
|
||||
},
|
||||
Address: catalog.AddressDetail{
|
||||
CountryCode: c.Address.CountryCode,
|
||||
City: c.Address.City,
|
||||
State: c.Address.State,
|
||||
Lat: c.Address.Lat,
|
||||
Long: c.Address.Long,
|
||||
},
|
||||
Seller: catalog.SellerDetail{
|
||||
ID: int(c.SellerID),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue