Compare commits
72 commits
8f0fbaac20
...
c113ac8a44
Author | SHA1 | Date | |
---|---|---|---|
c113ac8a44 | |||
9466d1b17a | |||
a70bd8bc79 | |||
84f10782b0 | |||
263a9d60ef | |||
a4317c8498 | |||
ceeb045154 | |||
030bdbe9e3 | |||
ee2f033b0d | |||
34f1404adb | |||
3113c9f01a | |||
1288e7da35 | |||
b77e2b8c3a | |||
fb971236f9 | |||
2f21ebee44 | |||
2e9b9e6adf | |||
5d0fe5edb5 | |||
eb60145ca2 | |||
3762b9695c | |||
d427ef4377 | |||
401ba892f7 | |||
dce7e59983 | |||
001e352e57 | |||
a224f0e212 | |||
72b9602f71 | |||
f4daca892e | |||
9152a2697b | |||
6c2aaa2f6e | |||
c58c1f1cc0 | |||
f1e698d867 | |||
48a801f725 | |||
96b12f797e | |||
996b20e67b | |||
821a8d5b68 | |||
96a461db0a | |||
da632d0787 | |||
f00fbb47cd | |||
f1a09882c5 | |||
a37f928604 | |||
dca773455a | |||
1dac480546 | |||
9a77fbd8cc | |||
838d737f65 | |||
6cdc6cfdac | |||
df771a3580 | |||
e3face9c03 | |||
65ad585a7c | |||
afd4e21a4c | |||
d45f5792a4 | |||
371a702f87 | |||
7c045ee9ef | |||
0b6b42351d | |||
830077b8cb | |||
305a84dd67 | |||
f15711a217 | |||
5b772a2d8a | |||
02d535e033 | |||
82f3c700fa | |||
fc22dc4e47 | |||
64c36c4b60 | |||
dc30b80b7c | |||
e8836764ea | |||
51bf915052 | |||
d93086b594 | |||
6e652317fe | |||
b0560d0c45 | |||
b25072377d | |||
4a47b4ba90 | |||
a2770334ed | |||
5448f4f8df | |||
b456549a90 | |||
77cdc064c6 |
525 changed files with 11405 additions and 4044 deletions
|
@ -2,4 +2,4 @@ bindata.go
|
|||
vendor/
|
||||
happydomain.db/
|
||||
happydomain.sock
|
||||
ui/node_modules/
|
||||
web/node_modules/
|
88
.drone.yml
88
.drone.yml
|
@ -14,7 +14,7 @@ steps:
|
|||
- apk --no-cache add tar
|
||||
- yarn config set network-timeout 100000
|
||||
- yarn --cwd ui install
|
||||
- tar --transform="s@.@./happydomain-${DRONE_COMMIT}@" --exclude-vcs --exclude=./ui/node_modules/.cache -czf /dev/shm/happydomain-src.tar.gz .
|
||||
- tar --transform="s@.@./happydomain-${DRONE_COMMIT}@" --exclude-vcs --exclude=./web/node_modules/.cache -czf /dev/shm/happydomain-src.tar.gz .
|
||||
- mv /dev/shm/happydomain-src.tar.gz .
|
||||
- yarn --cwd ui --offline build
|
||||
|
||||
|
@ -57,10 +57,10 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -73,10 +73,10 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X main.Version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X main.Version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -84,15 +84,6 @@ steps:
|
|||
event:
|
||||
- tag
|
||||
|
||||
- name: vet and tests
|
||||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- go vet -v ./...
|
||||
- go test -v ./...
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
- name: deploy
|
||||
image: plugins/s3
|
||||
settings:
|
||||
|
@ -132,7 +123,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: darwin
|
||||
|
@ -146,7 +137,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: darwin
|
||||
|
@ -203,6 +194,9 @@ steps:
|
|||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
exclude:
|
||||
- renovate/*
|
||||
event:
|
||||
- cron
|
||||
- push
|
||||
|
@ -229,10 +223,10 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -245,10 +239,10 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X main.Version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X main.Version=${DRONE_TAG##v} -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH} happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -256,6 +250,15 @@ steps:
|
|||
event:
|
||||
- tag
|
||||
|
||||
- name: vet and tests
|
||||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- go vet ./...
|
||||
- go test ./...
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
||||
- name: deploy
|
||||
image: plugins/s3
|
||||
settings:
|
||||
|
@ -295,7 +298,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: darwin
|
||||
|
@ -309,7 +312,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk add --no-cache git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-darwin-${DRONE_STAGE_ARCH} ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOOS: darwin
|
||||
|
@ -392,10 +395,11 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}el ./cmd/happyDomain/
|
||||
- go mod vendor
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}el ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOARM: 5
|
||||
|
@ -411,10 +415,11 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- sed -i '/npm run build/d' ui/assets.go
|
||||
- sed -i '/npm run build/d' web/assets.go
|
||||
- go install github.com/swaggo/swag/cmd/swag@latest
|
||||
- go generate -v ./...
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}el ./cmd/happyDomain/
|
||||
- go mod vendor
|
||||
- go generate ./...
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}el ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOARM: 5
|
||||
|
@ -461,7 +466,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}hf ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}hf ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOARM: 6
|
||||
|
@ -477,7 +482,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}hf ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}hf ./cmd/happyDomain/
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
GOARM: 6
|
||||
|
@ -524,10 +529,10 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- "[ -f docs/docs.go ] || sed -i '/npm run build/d' ui/assets.go"
|
||||
- "[ -f docs/docs.go ] || sed -i '/npm run build/d' web/assets.go"
|
||||
- "[ -f docs/docs.go ] || go install github.com/swaggo/swag/cmd/swag@latest"
|
||||
- "[ -f docs/docs.go ] || go generate -v ./..."
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 ./cmd/happyDomain/
|
||||
- "[ -f docs/docs.go ] || go generate ./..."
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_BRANCH}-${DRONE_COMMIT}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -541,7 +546,7 @@ steps:
|
|||
image: golang:1-alpine
|
||||
commands:
|
||||
- apk --no-cache add build-base git
|
||||
- go build -v -tags netgo,swagger,ui -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 ./cmd/happyDomain/
|
||||
- go build -tags netgo,swagger,web -ldflags '-w -X "main.Version=${DRONE_TAG##v}" -X main.build=${DRONE_BUILD_NUMBER}' -o happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 ./cmd/happyDomain/
|
||||
- ln happydomain-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}v7 happydomain
|
||||
environment:
|
||||
CGO_ENABLED: 0
|
||||
|
@ -609,6 +614,10 @@ trigger:
|
|||
kind: pipeline
|
||||
name: docker-manifest
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- name: publish on Docker Hub
|
||||
image: plugins/manifest
|
||||
|
@ -622,6 +631,9 @@ steps:
|
|||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
exclude:
|
||||
- renovate/*
|
||||
event:
|
||||
- cron
|
||||
- push
|
||||
|
|
16
Dockerfile
16
Dockerfile
|
@ -2,11 +2,11 @@ FROM node:22-alpine AS nodebuild
|
|||
|
||||
WORKDIR /go/src/git.happydns.org/happydomain
|
||||
|
||||
COPY ui/ ui/
|
||||
COPY web/ web/
|
||||
|
||||
RUN yarn config set network-timeout 100000 && \
|
||||
yarn --cwd ui install && \
|
||||
yarn --cwd ui --offline build
|
||||
yarn --cwd web install && \
|
||||
yarn --cwd web --offline build
|
||||
|
||||
|
||||
FROM golang:1-alpine AS gobuild
|
||||
|
@ -16,22 +16,18 @@ RUN apk add --no-cache git
|
|||
WORKDIR /go/src/git.happydns.org/happydomain
|
||||
|
||||
COPY --from=nodebuild /go/src/git.happydns.org/happydomain/ ./
|
||||
COPY adapters ./adapters
|
||||
COPY api ./api
|
||||
COPY api-admin ./api-admin
|
||||
COPY cmd ./cmd
|
||||
COPY generators ./generators
|
||||
COPY tools ./tools
|
||||
COPY internal ./internal
|
||||
COPY model ./model
|
||||
COPY providers ./providers
|
||||
COPY services ./services
|
||||
COPY usecase ./usecase
|
||||
COPY generate.go go.mod go.sum ./
|
||||
|
||||
RUN sed -i '/npm run build/d' ui/assets.go && \
|
||||
RUN sed -i '/npm run build/d' web/assets.go && \
|
||||
go install github.com/swaggo/swag/cmd/swag@latest && \
|
||||
go generate -v ./... && \
|
||||
go build -v -tags netgo,swagger,ui -ldflags '-w' ./cmd/happyDomain/
|
||||
go build -v -tags netgo,swagger,web -ldflags '-w' ./cmd/happyDomain/
|
||||
|
||||
|
||||
FROM alpine:3.21
|
||||
|
|
26
README.md
26
README.md
|
@ -1,7 +1,7 @@
|
|||
happyDomain
|
||||
===========
|
||||
|
||||
Finally a simple, modern and open source interface for domain name.
|
||||
happyDomain is a free web application that centralizes the management of your domain names from different registrars and hosts.
|
||||
|
||||

|
||||
|
||||
|
@ -12,13 +12,19 @@ It runs as a single stateless Linux binary, backed by a database (currently: Lev
|
|||
|
||||
* An ultra fast web interface without compromise
|
||||
* Multiple domains management
|
||||
* Support for 36+ DNS providers (including dynamic DNS, RFC 2136) thanks to [DNSControl](https://stackexchange.github.io/dnscontrol/)
|
||||
* Support for 44+ DNS providers (including dynamic DNS, RFC 2136) thanks to [DNSControl](https://stackexchange.github.io/dnscontrol/)
|
||||
* Support for the most recents resource records thanks to [CoreDNS's library](https://github.com/miekg/dns)
|
||||
* Zone editor with a diff view to review the changes before propagation
|
||||
* Keep an history of published changes
|
||||
* Contextual help
|
||||
* Multiple user with authentication or one user without authtication
|
||||
* Compatible with external authentication (through JWT tokens: Auth0, ...)
|
||||
* Multiple users with authentication or one user without authtication
|
||||
* Compatible with external authentication (OpenId Connect or through JWT tokens: Auth0, ...)
|
||||
|
||||
**happyDomain is functional but still very much a work in progress: it's a carefully crafted proof of concept that evolves thanks to you!**
|
||||
|
||||
Given the diversity of DNS configurations and user needs, we haven't yet identified all the bugs. **If something doesn't work, please don't leave: [tell us what's wrong](https://github.com/happyDomain/happydomain/issues).** We're highly responsive and each reported bug helps us improve the tool for everyone.
|
||||
|
||||
[Whether it works for you or not, we need your feedback!](https://feedback.happydomain.org/) What do you think of our approach to simplifying domain name management? Your impressions at this stage help us guide the project according to **your actual expectations**.
|
||||
|
||||
Using Docker
|
||||
------------
|
||||
|
@ -40,8 +46,8 @@ Building
|
|||
|
||||
In order to build the happyDomain project, you'll need the following dependencies:
|
||||
|
||||
* `go` at least version 1.21;
|
||||
* `nodejs` tested with version 20 and 21.
|
||||
* `go` at least version 1.23;
|
||||
* `nodejs` tested with version 22.
|
||||
|
||||
|
||||
### Instructions
|
||||
|
@ -49,7 +55,7 @@ In order to build the happyDomain project, you'll need the following dependencie
|
|||
1. First, you'll need to prepare the frontend, by installing the node modules dependencies:
|
||||
|
||||
```
|
||||
pushd ui; npm install; popd
|
||||
pushd web; npm install; popd
|
||||
```
|
||||
|
||||
2. Then, generate assets files used by Go code:
|
||||
|
@ -61,7 +67,7 @@ go generate ./...
|
|||
3. Finaly, build the Go code:
|
||||
|
||||
```
|
||||
go build -tags listmonk,swagger,ui
|
||||
go build -tags swagger,web ./cmd/happyDomain
|
||||
```
|
||||
|
||||
This last command will create a binary `happyDomain` you can use standalone.
|
||||
|
@ -158,13 +164,13 @@ If you want to contribute to the frontend, instead of regenerating the frontend
|
|||
In one terminal, run `happydomain` with the following arguments:
|
||||
|
||||
```
|
||||
./happyDomain -dev http://127.0.0.1:8080
|
||||
./happyDomain -dev http://127.0.0.1:5173
|
||||
```
|
||||
|
||||
In another terminal, run the node part:
|
||||
|
||||
```
|
||||
cd ui; npm run dev
|
||||
cd web; npm run dev
|
||||
```
|
||||
|
||||
With this setup, static assets integrated inside the go binary will not be used, instead it'll forward all requests for static assets to the node server, that do dynamic reload, etc.
|
||||
|
|
|
@ -32,9 +32,10 @@ import (
|
|||
"github.com/earthboundkid/versioninfo/v2"
|
||||
"github.com/fatih/color"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/app"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
_ "git.happydns.org/happyDomain/internal/storage/inmemory"
|
||||
_ "git.happydns.org/happyDomain/internal/storage/leveldb"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
_ "git.happydns.org/happyDomain/services/abstract"
|
||||
|
@ -66,7 +67,7 @@ func main() {
|
|||
color.NoColor = true
|
||||
|
||||
// Load and parse options
|
||||
var opts *config.Options
|
||||
var opts *happydns.Options
|
||||
if opts, err = config.ConsolidateConfig(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
|
||||
package main
|
||||
|
||||
//go:generate go run generators/gen_icon.go providers providers
|
||||
//go:generate go run generators/gen_icon.go services svcs
|
||||
//go:generate go run tools/gen_icon.go providers providers
|
||||
//go:generate go run tools/gen_icon.go services svcs
|
||||
//go:generate swag init --generalInfo api/route/route.go
|
||||
|
|
57
go.mod
57
go.mod
|
@ -4,24 +4,24 @@ go 1.23.0
|
|||
|
||||
require (
|
||||
github.com/StackExchange/dnscontrol/v4 v4.3.0
|
||||
github.com/coreos/go-oidc/v3 v3.12.0
|
||||
github.com/coreos/go-oidc/v3 v3.14.1
|
||||
github.com/earthboundkid/versioninfo/v2 v2.24.1
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/gin-contrib/sessions v1.0.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/gin-gonic/gin v1.10.1
|
||||
github.com/go-mail/mail v2.3.1+incompatible
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/gorilla/securecookie v1.1.2
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
github.com/miekg/dns v1.1.63
|
||||
github.com/miekg/dns v1.1.66
|
||||
github.com/mileusna/useragent v1.3.5
|
||||
github.com/ovh/go-ovh v1.6.0
|
||||
github.com/ovh/go-ovh v1.7.0
|
||||
github.com/rrivera/identicon v0.0.0-20240116195454-d5ba35832c0d
|
||||
github.com/swaggo/swag v1.16.4
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/oauth2 v0.25.0
|
||||
github.com/yuin/goldmark v1.7.12
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -60,12 +60,11 @@ require (
|
|||
github.com/aws/smithy-go v1.20.4 // indirect
|
||||
github.com/billputer/go-namecheap v0.0.0-20210108011502-994a912fb7f9 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v4 v4.0.7 // indirect
|
||||
github.com/cloudflare/cloudflare-go v0.103.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.9.1 // indirect
|
||||
github.com/digitalocean/godo v1.121.0 // indirect
|
||||
|
@ -74,10 +73,10 @@ require (
|
|||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/go-gandi/go-gandi v0.7.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
|
@ -86,12 +85,12 @@ require (
|
|||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
|
@ -104,7 +103,7 @@ require (
|
|||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
|
@ -121,7 +120,7 @@ require (
|
|||
github.com/onsi/ginkgo v1.16.4 // indirect
|
||||
github.com/oracle/oci-go-sdk/v65 v65.73.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/peterhellberg/link v1.1.0 // indirect
|
||||
github.com/philhug/opensrs-go v0.0.0-20171126225031-9dfa7433020d // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
|
@ -135,7 +134,7 @@ require (
|
|||
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
|
||||
github.com/sony/gobreaker v0.5.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/transip/gotransip/v6 v6.26.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
|
@ -145,19 +144,19 @@ require (
|
|||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/arch v0.16.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
google.golang.org/api v0.195.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240823204242-4ba0660f739c // indirect
|
||||
google.golang.org/grpc v1.65.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/mail.v2 v2.3.1 // indirect
|
||||
|
|
129
go.sum
129
go.sum
|
@ -75,23 +75,23 @@ github.com/billputer/go-namecheap v0.0.0-20210108011502-994a912fb7f9/go.mod h1:b
|
|||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v4 v4.0.7 h1:Jk7uhY5q11fE5PlEupX2Lo12w82UhGC6bE1CI5jwFbc=
|
||||
github.com/centralnicgroup-opensource/rtldev-middleware-go-sdk/v4 v4.0.7/go.mod h1:FnQtD0+Q/1NZxi0eEWN+3ZRyMsE9vzSB3YjyunkbKD0=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/cloudflare-go v0.103.0 h1:XXKzgXeUbAo7UTtM4T5wuD2bJPBtNZv7TlZAEy5QI4k=
|
||||
github.com/cloudflare/cloudflare-go v0.103.0/go.mod h1:0DrjT4g8wgYFYIxhlqR8xi8dNWfyHFGilUkU3+XV8h0=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
|
||||
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -123,22 +123,25 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA=
|
||||
github.com/gin-contrib/sessions v1.0.2/go.mod h1:KxKxWqWP5LJVDCInulOl4WbLzK2KSPlLesfZ66wRvMs=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
||||
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
|
||||
github.com/go-gandi/go-gandi v0.7.0 h1:gsP33dUspsN1M+ZW9HEgHchK9HiaSkYnltO73RHhSZA=
|
||||
github.com/go-gandi/go-gandi v0.7.0/go.mod h1:9NoYyfWCjFosClPiWjkbbRK5UViaZ4ctpT8/pKSSFlw=
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
|
||||
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
@ -169,23 +172,23 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe h1:zn8tqiUbec4wR94o7Qj3LZCAT6uGobhEgnDRg6isG5U=
|
||||
github.com/gobwas/glob v0.2.4-0.20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
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-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
|
@ -205,8 +208,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
|||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
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=
|
||||
|
@ -273,8 +276,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
|
|||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
|
||||
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
|
||||
|
@ -318,8 +321,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
|
||||
github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
|
||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
||||
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
||||
github.com/mileusna/useragent v1.3.5 h1:SJM5NzBmh/hO+4LGeATKpaEX9+b4vcGg2qXGLiNGDws=
|
||||
github.com/mileusna/useragent v1.3.5/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
|
@ -357,12 +362,12 @@ github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
|||
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.73.0 h1:C7uel6CoKk4A1KPkdhFBAyvVyFRTHAmX8m0o64RmfPg=
|
||||
github.com/oracle/oci-go-sdk/v65 v65.73.0/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0=
|
||||
github.com/ovh/go-ovh v1.6.0 h1:ixLOwxQdzYDx296sXcgS35TOPEahJkpjMGtzPadCjQI=
|
||||
github.com/ovh/go-ovh v1.6.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
||||
github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/peterhellberg/link v1.1.0 h1:s2+RH8EGuI/mI4QwrWGSYQCRz7uNgip9BaM04HKu5kc=
|
||||
github.com/peterhellberg/link v1.1.0/go.mod h1:gtSlOT4jmkY8P47hbTc8PTgiDDWpdPbFYl75keYyBB8=
|
||||
github.com/philhug/opensrs-go v0.0.0-20171126225031-9dfa7433020d h1:nf4+lHs8TQeIGFYZMcNg4iQOnZndLfYxnQaKEdqHVA4=
|
||||
|
@ -420,8 +425,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
|
@ -449,6 +454,10 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
|
||||
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
|
||||
github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
|
@ -459,9 +468,8 @@ go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGX
|
|||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.16.0 h1:foMtLTdyOmIniqWCHjY6+JxuC54XP1fDwx4N0ASyW+U=
|
||||
golang.org/x/arch v0.16.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
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=
|
||||
|
@ -469,8 +477,10 @@ golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWP
|
|||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
|
||||
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
|
@ -481,8 +491,10 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -500,11 +512,15 @@ golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||
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/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
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.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -512,8 +528,10 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -545,8 +563,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
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=
|
||||
|
@ -559,8 +579,10 @@ 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/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
|
@ -577,8 +599,10 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
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=
|
||||
|
@ -614,8 +638,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
|||
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -656,4 +680,3 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8=
|
||||
moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
|
|
@ -23,6 +23,7 @@ package adapter
|
|||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -99,15 +100,21 @@ func NewDNSControlProviderAdapter(configAdapter DNSControlConfigAdapter) (happyd
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var auditor dnscontrol.RecordAuditor
|
||||
if p, ok := dnscontrol.DNSProviderTypes[configAdapter.DNSControlName()]; ok && p.RecordAuditor != nil {
|
||||
auditor = p.RecordAuditor
|
||||
}
|
||||
|
||||
if _, ok := provider.(dnscontrol.ZoneLister); ok {
|
||||
return &DNSControlAdapterNSProviderWithListZone{DNSControlAdapterNSProvider{provider}}, nil
|
||||
return &DNSControlAdapterNSProviderWithListZone{DNSControlAdapterNSProvider{provider, auditor}}, nil
|
||||
} else {
|
||||
return &DNSControlAdapterNSProvider{provider}, nil
|
||||
return &DNSControlAdapterNSProvider{provider, auditor}, nil
|
||||
}
|
||||
}
|
||||
|
||||
type DNSControlAdapterNSProvider struct {
|
||||
dnscontrol.DNSServiceProvider
|
||||
DNSServiceProvider dnscontrol.DNSServiceProvider
|
||||
RecordAuditor dnscontrol.RecordAuditor
|
||||
}
|
||||
|
||||
func (p *DNSControlAdapterNSProvider) CanListZones() bool {
|
||||
|
@ -148,6 +155,12 @@ func (p *DNSControlAdapterNSProvider) GetZoneCorrections(domain string, rrs []ha
|
|||
return
|
||||
}
|
||||
|
||||
errs := p.RecordAuditor(dc.Records)
|
||||
if errs != nil {
|
||||
err = fmt.Errorf("some records are incompatibles with this NS provider: %w. Please fix those errors and retry.", errors.Join(errs...))
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if a := recover(); a != nil {
|
||||
err = fmt.Errorf("%s", a)
|
|
@ -28,18 +28,18 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/utils"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/helpers"
|
||||
"git.happydns.org/happyDomain/internal/usecase/authuser"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type AuthUserController struct {
|
||||
auService happydns.AuthUserUsecase
|
||||
store storage.Storage
|
||||
store authuser.AuthUserStorage
|
||||
}
|
||||
|
||||
func NewAuthUserController(auService happydns.AuthUserUsecase, store storage.Storage) *AuthUserController {
|
||||
func NewAuthUserController(auService happydns.AuthUserUsecase, store authuser.AuthUserStorage) *AuthUserController {
|
||||
return &AuthUserController{
|
||||
auService,
|
||||
store,
|
||||
|
@ -62,7 +62,18 @@ func (ac *AuthUserController) AuthUserHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (ac *AuthUserController) GetAuthUsers(c *gin.Context) {
|
||||
users, err := ac.store.GetAuthUsers()
|
||||
iter, err := ac.store.ListAllAuthUsers()
|
||||
if err != nil {
|
||||
happydns.ApiResponse(c, nil, err)
|
||||
return
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
var users []*happydns.UserAuth
|
||||
for iter.Next() {
|
||||
users = append(users, iter.Item())
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, users, err)
|
||||
}
|
||||
|
||||
|
@ -111,13 +122,14 @@ func (ac *AuthUserController) DeleteAuthUser(c *gin.Context) {
|
|||
func (ac *AuthUserController) EmailValidationLink(c *gin.Context) {
|
||||
user := c.MustGet("authuser").(*happydns.UserAuth)
|
||||
|
||||
happydns.ApiResponse(c, ac.auService.GetValidationLink(user), nil)
|
||||
happydns.ApiResponse(c, ac.auService.GenerateValidationLink(user), nil)
|
||||
}
|
||||
|
||||
func (ac *AuthUserController) RecoverUserAcct(c *gin.Context) {
|
||||
user := c.MustGet("authuser").(*happydns.UserAuth)
|
||||
|
||||
happydns.ApiResponse(c, ac.auService.GetRecoveryLink(user), nil)
|
||||
link, err := ac.auService.GenerateRecoveryLink(user)
|
||||
happydns.ApiResponse(c, link, err)
|
||||
}
|
||||
|
||||
type resetPassword struct {
|
||||
|
@ -135,7 +147,7 @@ func (ac *AuthUserController) ResetUserPasswd(c *gin.Context) {
|
|||
}
|
||||
|
||||
if urp.Password == "" {
|
||||
urp.Password, err = utils.GeneratePassword()
|
||||
urp.Password, err = helpers.GeneratePassword()
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, happydns.ErrorResponse{Message: err.Error()})
|
||||
return
|
|
@ -29,18 +29,18 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
providerUC "git.happydns.org/happyDomain/internal/usecase/provider"
|
||||
zoneUC "git.happydns.org/happyDomain/internal/usecase/zone"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/usecase"
|
||||
)
|
||||
|
||||
type BackupController struct {
|
||||
config *config.Options
|
||||
config *happydns.Options
|
||||
store storage.Storage
|
||||
}
|
||||
|
||||
func NewBackupController(cfg *config.Options, store storage.Storage) *BackupController {
|
||||
func NewBackupController(cfg *happydns.Options, store storage.Storage) *BackupController {
|
||||
return &BackupController{
|
||||
config: cfg,
|
||||
store: store,
|
||||
|
@ -52,23 +52,30 @@ func (bc *BackupController) DoBackup() (ret happydns.Backup) {
|
|||
ret.DomainsLogs = map[string][]*happydns.DomainLog{}
|
||||
|
||||
// UserAuth
|
||||
uas, err := bc.store.GetAuthUsers()
|
||||
uai, err := bc.store.ListAllAuthUsers()
|
||||
if err != nil {
|
||||
ret.Errors = append(ret.Errors, fmt.Sprintf("unable to retrieve AuthUsers: %s", err.Error()))
|
||||
} else {
|
||||
ret.UsersAuth = uas
|
||||
defer uai.Close()
|
||||
for uai.Next() {
|
||||
ret.UsersAuth = append(ret.UsersAuth, uai.Item())
|
||||
}
|
||||
}
|
||||
|
||||
// Users
|
||||
us, err := bc.store.GetUsers()
|
||||
iter, err := bc.store.ListAllUsers()
|
||||
if err != nil {
|
||||
ret.Errors = append(ret.Errors, fmt.Sprintf("unable to retrieve Users: %s", err.Error()))
|
||||
} else {
|
||||
ret.Users = us
|
||||
defer iter.Close()
|
||||
|
||||
for iter.Next() {
|
||||
u := iter.Item()
|
||||
|
||||
ret.Users = append(ret.Users, u)
|
||||
|
||||
for _, u := range us {
|
||||
// Domains
|
||||
ds, err := bc.store.GetDomains(u)
|
||||
ds, err := bc.store.ListDomains(u)
|
||||
if err != nil {
|
||||
ret.Errors = append(ret.Errors, fmt.Sprintf("unable to retrieve Domain names of %s (%s): %s", u.Id.String(), u.Email, err.Error()))
|
||||
} else {
|
||||
|
@ -76,7 +83,7 @@ func (bc *BackupController) DoBackup() (ret happydns.Backup) {
|
|||
|
||||
for _, dn := range ds {
|
||||
// Domain logs
|
||||
ls, err := bc.store.GetDomainLogs(dn)
|
||||
ls, err := bc.store.ListDomainLogs(dn)
|
||||
if err != nil {
|
||||
ret.Errors = append(ret.Errors, fmt.Sprintf("unable to retrieve domain's logs %s/%s (%s): %s", u.Id.String(), dn.Id.String(), dn.DomainName, err.Error()))
|
||||
} else {
|
||||
|
@ -104,7 +111,7 @@ func (bc *BackupController) DoBackup() (ret happydns.Backup) {
|
|||
}
|
||||
|
||||
// Sessions
|
||||
ss, err := bc.store.GetUserSessions(u.Id)
|
||||
ss, err := bc.store.ListUserSessions(u.Id)
|
||||
if err != nil {
|
||||
ret.Errors = append(ret.Errors, fmt.Sprintf("unable to retrieve Sessions: %s", err.Error()))
|
||||
} else {
|
||||
|
@ -132,7 +139,7 @@ func (bc *BackupController) DoRestore(backup *happydns.Backup) (errs error) {
|
|||
|
||||
// Providers
|
||||
for _, provider := range backup.Providers {
|
||||
p, err := usecase.ParseProvider(provider)
|
||||
p, err := providerUC.ParseProvider(provider)
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
|
@ -155,7 +162,7 @@ func (bc *BackupController) DoRestore(backup *happydns.Backup) (errs error) {
|
|||
|
||||
// Zones
|
||||
for _, zmsg := range backup.Zones {
|
||||
zone, err := usecase.ParseZone(zmsg)
|
||||
zone, err := zoneUC.ParseZone(zmsg)
|
||||
if err != nil {
|
||||
errs = errors.Join(errs, err)
|
||||
} else {
|
|
@ -29,20 +29,24 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/usecase/domain"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type DomainController struct {
|
||||
domainService happydns.DomainUsecase
|
||||
store storage.Storage
|
||||
domainService happydns.DomainUsecase
|
||||
remoteZoneImporter happydns.RemoteZoneImporterUsecase
|
||||
zoneImporter happydns.ZoneImporterUsecase
|
||||
store domain.DomainStorage
|
||||
}
|
||||
|
||||
func NewDomainController(duService happydns.DomainUsecase, store storage.Storage) *DomainController {
|
||||
func NewDomainController(duService happydns.DomainUsecase, remoteZoneImporter happydns.RemoteZoneImporterUsecase, zoneImporter happydns.ZoneImporterUsecase, store domain.DomainStorage) *DomainController {
|
||||
return &DomainController{
|
||||
duService,
|
||||
remoteZoneImporter,
|
||||
zoneImporter,
|
||||
store,
|
||||
}
|
||||
}
|
||||
|
@ -50,26 +54,21 @@ func NewDomainController(duService happydns.DomainUsecase, store storage.Storage
|
|||
func (dc *DomainController) ListDomains(c *gin.Context) {
|
||||
user := middleware.MyUser(c)
|
||||
if user != nil {
|
||||
apidc := controller.NewDomainController(dc.domainService)
|
||||
apidc := controller.NewDomainController(dc.domainService, dc.remoteZoneImporter, dc.zoneImporter)
|
||||
apidc.GetDomains(c)
|
||||
return
|
||||
}
|
||||
|
||||
var domains happydns.Domains
|
||||
|
||||
users, err := dc.store.GetUsers()
|
||||
iter, err := dc.store.ListAllDomains()
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to retrieve users list: %w", err))
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to retrieve domains list: %w", err))
|
||||
return
|
||||
}
|
||||
for _, user := range users {
|
||||
usersDomains, err := dc.store.GetDomains(user)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to retrieve %s's domains: %w", user.Email, err))
|
||||
return
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
domains = append(domains, usersDomains...)
|
||||
var domains []*happydns.Domain
|
||||
for iter.Next() {
|
||||
domains = append(domains, iter.Item())
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, domains, nil)
|
||||
|
@ -85,9 +84,9 @@ func (dc *DomainController) NewDomain(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
ud.Id = nil
|
||||
ud.IdUser = user.Id
|
||||
ud.Owner = user.Id
|
||||
|
||||
happydns.ApiResponse(c, ud, dc.store.CreateDomain(user, ud))
|
||||
happydns.ApiResponse(c, ud, dc.store.CreateDomain(ud))
|
||||
}
|
||||
|
||||
func (dc *DomainController) DeleteDomain(c *gin.Context) {
|
||||
|
@ -103,35 +102,36 @@ func (dc *DomainController) DeleteDomain(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
domain, err := dc.store.GetDomainByDN(user, c.Param("domain"))
|
||||
domains, err := dc.store.GetDomainByDN(user, c.Param("domain"))
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusNotFound, err)
|
||||
return
|
||||
} else {
|
||||
domainid = domain.Id
|
||||
}
|
||||
|
||||
if len(domains) != 1 {
|
||||
middleware.ErrorResponse(c, http.StatusNotFound, fmt.Errorf("too many domains with this FQDN, use domain identifier instead"))
|
||||
return
|
||||
}
|
||||
|
||||
domainid = domains[0].Id
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, true, dc.store.DeleteDomain(domainid))
|
||||
}
|
||||
|
||||
func (dc *DomainController) searchUserDomain(filter func(*happydns.Domain) bool) *happydns.User {
|
||||
users, err := dc.store.GetUsers()
|
||||
iter, err := dc.store.ListAllDomains()
|
||||
if err != nil {
|
||||
log.Println("Unable to retrieve users list:", err.Error())
|
||||
log.Println("Unable to retrieve domains list:", err.Error())
|
||||
return nil
|
||||
}
|
||||
for _, user := range users {
|
||||
usersDomains, err := dc.store.GetDomains(user)
|
||||
if err != nil {
|
||||
log.Printf("Unable to retrieve %s's domains: %s", user.Email, err.Error())
|
||||
continue
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for _, domain := range usersDomains {
|
||||
if filter(domain) {
|
||||
return user
|
||||
}
|
||||
for iter.Next() {
|
||||
domain := iter.Item()
|
||||
if filter(domain) {
|
||||
// Create a fake minimal user, as only the Id is required to perform further actions on database
|
||||
return &happydns.User{Id: domain.Owner}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,17 @@ func (dc *DomainController) GetDomain(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
domain, err := dc.store.GetDomain(user, domainid)
|
||||
domain, err := dc.store.GetDomain(domainid)
|
||||
if err != nil {
|
||||
happydns.ApiResponse(c, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !user.Id.Equals(domain.Owner) {
|
||||
happydns.ApiResponse(c, nil, fmt.Errorf("domain not found"))
|
||||
return
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, domain, err)
|
||||
}
|
||||
}
|
||||
|
@ -180,13 +190,6 @@ func (dc *DomainController) UpdateDomain(c *gin.Context) {
|
|||
}
|
||||
ud.Id = domain.Id
|
||||
|
||||
if !ud.IdUser.Equals(domain.IdUser) {
|
||||
if err := dc.store.UpdateDomainOwner(domain, &happydns.User{Id: ud.IdUser}); err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, ud, dc.store.UpdateDomain(ud))
|
||||
}
|
||||
|
||||
|
@ -217,3 +220,15 @@ func (dc *DomainController) ClearDomains(c *gin.Context) {
|
|||
|
||||
happydns.ApiResponse(c, true, dc.store.ClearDomains())
|
||||
}
|
||||
|
||||
func (dc *DomainController) UpdateZones(c *gin.Context) {
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
|
||||
err := c.ShouldBindJSON(&domain.ZoneHistory)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusNotFound, fmt.Errorf("something is wrong in received data: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, domain, dc.store.UpdateDomain(domain))
|
||||
}
|
|
@ -28,18 +28,18 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/usecase/provider"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type ProviderController struct {
|
||||
providerService happydns.ProviderUsecase
|
||||
store storage.Storage
|
||||
store provider.ProviderStorage
|
||||
}
|
||||
|
||||
func NewProviderController(providerService happydns.ProviderUsecase, store storage.Storage) *ProviderController {
|
||||
func NewProviderController(providerService happydns.ProviderUsecase, store provider.ProviderStorage) *ProviderController {
|
||||
return &ProviderController{
|
||||
providerService,
|
||||
store,
|
||||
|
@ -54,25 +54,20 @@ func (pc *ProviderController) ListProviders(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
var providers []*happydns.ProviderMeta
|
||||
|
||||
users, err := pc.store.GetUsers()
|
||||
iter, err := pc.store.ListAllProviders()
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to list users: %w", err))
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to list providers: %w", err))
|
||||
return
|
||||
}
|
||||
defer iter.Close()
|
||||
|
||||
for _, user := range users {
|
||||
usersProviders, err := pc.store.ListProviders(user)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, fmt.Errorf("unable to list users: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
providers = append(providers, usersProviders.Metas()...)
|
||||
var res []*happydns.ProviderMeta
|
||||
for iter.Next() {
|
||||
provider := iter.Item()
|
||||
res = append(res, &provider.ProviderMeta)
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, providers, nil)
|
||||
happydns.ApiResponse(c, res, nil)
|
||||
}
|
||||
|
||||
func (pc *ProviderController) AddProvider(c *gin.Context) {
|
|
@ -27,27 +27,26 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
serviceUC "git.happydns.org/happyDomain/internal/usecase/service"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/usecase"
|
||||
)
|
||||
|
||||
type ServiceController struct {
|
||||
serviceService happydns.ServiceUsecase
|
||||
zoneService happydns.ZoneUsecase
|
||||
store storage.Storage
|
||||
zoneServiceUC happydns.ZoneServiceUsecase
|
||||
}
|
||||
|
||||
func NewServiceController(serviceService happydns.ServiceUsecase, zoneService happydns.ZoneUsecase, store storage.Storage) *ServiceController {
|
||||
func NewServiceController(serviceService happydns.ServiceUsecase, zoneServiceUC happydns.ZoneServiceUsecase) *ServiceController {
|
||||
return &ServiceController{
|
||||
serviceService,
|
||||
zoneService,
|
||||
store,
|
||||
zoneServiceUC,
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *ServiceController) DeleteZoneService(c *gin.Context) {
|
||||
user := middleware.MyUser(c)
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
serviceid := c.MustGet("serviceid").(happydns.Identifier)
|
||||
|
||||
|
@ -57,7 +56,7 @@ func (sc *ServiceController) DeleteZoneService(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err := sc.zoneService.DeleteService(zone, subdomain, serviceid)
|
||||
zone, err := sc.zoneServiceUC.RemoveServiceFromZone(user, domain, zone, subdomain, serviceid)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -76,6 +75,8 @@ func (sc *ServiceController) GetZoneService(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (sc *ServiceController) UpdateZoneService(c *gin.Context) {
|
||||
user := middleware.MyUser(c)
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
serviceid := c.MustGet("serviceid").(happydns.Identifier)
|
||||
|
||||
|
@ -86,7 +87,7 @@ func (sc *ServiceController) UpdateZoneService(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
newservice, err := usecase.ParseService(&usc)
|
||||
newservice, err := serviceUC.ParseService(&usc)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusBadRequest, err)
|
||||
return
|
||||
|
@ -97,7 +98,7 @@ func (sc *ServiceController) UpdateZoneService(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err = sc.zoneService.UpdateService(zone, usc.Domain, usc.Id, newservice)
|
||||
zone, err = sc.zoneServiceUC.UpdateZoneService(user, domain, zone, happydns.Subdomain(usc.Domain), usc.Id, newservice)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
|
@ -26,17 +26,16 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/usecase/session"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type SessionController struct {
|
||||
config *config.Options
|
||||
store storage.Storage
|
||||
config *happydns.Options
|
||||
store session.SessionStorage
|
||||
}
|
||||
|
||||
func NewSessionController(cfg *config.Options, store storage.Storage) *SessionController {
|
||||
func NewSessionController(cfg *happydns.Options, store session.SessionStorage) *SessionController {
|
||||
return &SessionController{
|
||||
config: cfg,
|
||||
store: store,
|
42
internal/api-admin/controller/tidy_controller.go
Normal file
42
internal/api-admin/controller/tidy_controller.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2024 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type TidyController struct {
|
||||
tidyUpService happydns.TidyUpUseCase
|
||||
}
|
||||
|
||||
func NewTidyController(tidyUpService happydns.TidyUpUseCase) *TidyController {
|
||||
return &TidyController{
|
||||
tidyUpService: tidyUpService,
|
||||
}
|
||||
}
|
||||
|
||||
func (tc *TidyController) TidyDB(c *gin.Context) {
|
||||
happydns.ApiResponse(c, true, tc.tidyUpService.TidyAll())
|
||||
}
|
|
@ -27,17 +27,17 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/usecase/user"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
userService happydns.UserUsecase
|
||||
store storage.Storage
|
||||
store user.UserStorage
|
||||
}
|
||||
|
||||
func NewUserController(store storage.Storage, userService happydns.UserUsecase) *UserController {
|
||||
func NewUserController(store user.UserStorage, userService happydns.UserUsecase) *UserController {
|
||||
return &UserController{
|
||||
userService,
|
||||
store,
|
||||
|
@ -60,7 +60,17 @@ func (uc *UserController) UserHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (uc *UserController) GetUsers(c *gin.Context) {
|
||||
users, err := uc.store.GetUsers()
|
||||
iter, err := uc.store.ListAllUsers()
|
||||
if err != nil {
|
||||
happydns.ApiResponse(c, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
var users []*happydns.User
|
||||
for iter.Next() {
|
||||
users = append(users, iter.Item())
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, users, err)
|
||||
}
|
||||
|
||||
|
@ -104,7 +114,3 @@ func (uc *UserController) DeleteUser(c *gin.Context) {
|
|||
|
||||
happydns.ApiResponse(c, true, uc.store.DeleteUser(user.Id))
|
||||
}
|
||||
|
||||
func (uc *UserController) TidyDB(c *gin.Context) {
|
||||
happydns.ApiResponse(c, true, uc.store.Tidy())
|
||||
}
|
|
@ -27,22 +27,24 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/usecase/zone"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type ZoneController struct {
|
||||
domainService happydns.DomainUsecase
|
||||
zoneService happydns.ZoneUsecase
|
||||
store storage.Storage
|
||||
domainService happydns.DomainUsecase
|
||||
zoneService happydns.ZoneUsecase
|
||||
zoneCorrectionService happydns.ZoneCorrectionApplierUsecase
|
||||
store zone.ZoneStorage
|
||||
}
|
||||
|
||||
func NewZoneController(domainService happydns.DomainUsecase, zoneService happydns.ZoneUsecase, store storage.Storage) *ZoneController {
|
||||
func NewZoneController(domainService happydns.DomainUsecase, zoneService happydns.ZoneUsecase, zoneCorrectionService happydns.ZoneCorrectionApplierUsecase, store zone.ZoneStorage) *ZoneController {
|
||||
return &ZoneController{
|
||||
domainService,
|
||||
zoneService,
|
||||
zoneCorrectionService,
|
||||
store,
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ func (zc *ZoneController) DeleteZone(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (zc *ZoneController) GetZone(c *gin.Context) {
|
||||
apizc := controller.NewZoneController(zc.zoneService, zc.domainService)
|
||||
apizc := controller.NewZoneController(zc.zoneService, zc.domainService, zc.zoneCorrectionService)
|
||||
apizc.GetZone(c)
|
||||
}
|
||||
|
||||
|
@ -93,15 +95,3 @@ func (zc *ZoneController) UpdateZone(c *gin.Context) {
|
|||
|
||||
happydns.ApiResponse(c, uz, zc.store.UpdateZone(uz))
|
||||
}
|
||||
|
||||
func (zc *ZoneController) UpdateZones(c *gin.Context) {
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
|
||||
err := c.ShouldBindJSON(&domain.ZoneHistory)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusNotFound, fmt.Errorf("something is wrong in received data: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
happydns.ApiResponse(c, domain, zc.store.UpdateDomain(domain))
|
||||
}
|
|
@ -24,13 +24,13 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareUserAuthsRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
ac := controller.NewAuthUserController(dependancies.GetAuthUserService(), store)
|
||||
ac := controller.NewAuthUserController(dependancies.AuthUserUsecase(), store)
|
||||
|
||||
router.GET("/auth", ac.GetAuthUsers)
|
||||
router.POST("/auth", ac.NewAuthUser)
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareBackupRoutes(cfg *config.Options, router *gin.RouterGroup, store storage.Storage) {
|
||||
func declareBackupRoutes(cfg *happydns.Options, router *gin.RouterGroup, store storage.Storage) {
|
||||
bc := controller.NewBackupController(cfg, store)
|
||||
|
||||
router.POST("/backup.json", bc.BackupJSON)
|
|
@ -24,14 +24,19 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareDomainRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
dc := controller.NewDomainController(dependancies.GetDomainService(), store)
|
||||
dc := controller.NewDomainController(
|
||||
dependancies.DomainUsecase(),
|
||||
dependancies.RemoteZoneImporterUsecase(),
|
||||
dependancies.ZoneImporterUsecase(),
|
||||
store,
|
||||
)
|
||||
|
||||
router.GET("/domains", dc.ListDomains)
|
||||
router.POST("/domains", dc.NewDomain)
|
||||
|
@ -40,10 +45,11 @@ func declareDomainRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseD
|
|||
router.DELETE("/domains/:domain", dc.DeleteDomain)
|
||||
|
||||
apiDomainsRoutes := router.Group("/domains/:domain")
|
||||
apiDomainsRoutes.Use(middleware.DomainHandler(dependancies.GetDomainService(), true))
|
||||
apiDomainsRoutes.Use(middleware.DomainHandler(dependancies.DomainUsecase(), true))
|
||||
|
||||
apiDomainsRoutes.GET("", dc.GetDomain)
|
||||
apiDomainsRoutes.PUT("", dc.UpdateDomain)
|
||||
|
||||
apiDomainsRoutes.PUT("/zones", dc.UpdateZones)
|
||||
declareZoneRoutes(apiDomainsRoutes, dependancies, store)
|
||||
}
|
|
@ -24,27 +24,27 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareProviderRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
pc := controller.NewProviderController(dependancies.GetProviderService(false), store)
|
||||
pc := controller.NewProviderController(dependancies.ProviderUsecase(false), store)
|
||||
|
||||
router.GET("/providers", pc.ListProviders)
|
||||
router.POST("/providers", pc.AddProvider)
|
||||
router.DELETE("/providers", pc.ClearProviders)
|
||||
|
||||
apiProvidersMetaRoutes := router.Group("/providers/:pid")
|
||||
apiProvidersMetaRoutes.Use(middleware.ProviderMetaHandler(dependancies.GetProviderService(false)))
|
||||
apiProvidersMetaRoutes.Use(middleware.ProviderMetaHandler(dependancies.ProviderUsecase(false)))
|
||||
|
||||
apiProvidersMetaRoutes.PUT("", pc.UpdateProvider)
|
||||
apiProvidersMetaRoutes.DELETE("", pc.DeleteProvider)
|
||||
|
||||
apiProvidersRoutes := router.Group("/providers/:pid")
|
||||
apiProvidersRoutes.Use(middleware.ProviderHandler(dependancies.GetProviderService(false)))
|
||||
apiProvidersRoutes.Use(middleware.ProviderHandler(dependancies.ProviderUsecase(false)))
|
||||
|
||||
apiProvidersRoutes.GET("", pc.GetProvider)
|
||||
|
|
@ -24,13 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
api "git.happydns.org/happyDomain/api/route"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
api "git.happydns.org/happyDomain/internal/api/route"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareRoutes(cfg *config.Options, router *gin.Engine, s storage.Storage, dependancies happydns.UsecaseDependancies) {
|
||||
func DeclareRoutes(cfg *happydns.Options, router *gin.Engine, s storage.Storage, dependancies happydns.UsecaseDependancies) {
|
||||
apiRoutes := router.Group("/api")
|
||||
|
||||
declareBackupRoutes(cfg, apiRoutes, s)
|
||||
|
@ -39,5 +38,6 @@ func DeclareRoutes(cfg *config.Options, router *gin.Engine, s storage.Storage, d
|
|||
declareSessionsRoutes(cfg, apiRoutes, s)
|
||||
declareUserAuthsRoutes(apiRoutes, dependancies, s)
|
||||
declareUsersRoutes(apiRoutes, dependancies, s)
|
||||
declareTidyRoutes(apiRoutes, s)
|
||||
api.DeclareVersionRoutes(apiRoutes)
|
||||
}
|
|
@ -24,17 +24,20 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareZoneServiceRoutes(apiZonesRoutes *gin.RouterGroup, zc *controller.ZoneController, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
sc := controller.NewServiceController(dependancies.GetServiceService(), dependancies.GetZoneService(), store)
|
||||
sc := controller.NewServiceController(
|
||||
dependancies.ServiceUsecase(),
|
||||
dependancies.ZoneServiceUsecase(),
|
||||
)
|
||||
|
||||
apiZonesServiceIdRoutes := apiZonesRoutes.Group("/services/:serviceid")
|
||||
apiZonesServiceIdRoutes.Use(middleware.ServiceIdHandler(dependancies.GetServiceService()))
|
||||
apiZonesServiceIdRoutes.Use(middleware.ServiceIdHandler(dependancies.ServiceUsecase()))
|
||||
apiZonesServiceIdRoutes.GET("", sc.GetZoneService)
|
||||
apiZonesServiceIdRoutes.PUT("", sc.UpdateZoneService)
|
||||
apiZonesServiceIdRoutes.DELETE("", sc.DeleteZoneService)
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareSessionsRoutes(cfg *config.Options, router *gin.RouterGroup, store storage.Storage) {
|
||||
func declareSessionsRoutes(cfg *happydns.Options, router *gin.RouterGroup, store storage.Storage) {
|
||||
sc := controller.NewSessionController(cfg, store)
|
||||
|
||||
router.DELETE("/sessions", sc.DeleteSessions)
|
36
internal/api-admin/route/tidy.go
Normal file
36
internal/api-admin/route/tidy.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2024 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package route
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/usecase"
|
||||
)
|
||||
|
||||
func declareTidyRoutes(router *gin.RouterGroup, store storage.Storage) {
|
||||
tc := controller.NewTidyController(usecase.NewTidyUpUsecase(store))
|
||||
|
||||
router.POST("/tidy", tc.TidyDB)
|
||||
}
|
|
@ -24,13 +24,13 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareUsersRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
sc := controller.NewUserController(store, dependancies.GetUserService())
|
||||
sc := controller.NewUserController(store, dependancies.UserUsecase())
|
||||
|
||||
router.GET("/users", sc.GetUsers)
|
||||
router.POST("/users", sc.NewUser)
|
||||
|
@ -45,6 +45,4 @@ func declareUsersRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDe
|
|||
|
||||
declareDomainRoutes(apiUsersRoutes, dependancies, store)
|
||||
declareProviderRoutes(apiUsersRoutes, dependancies, store)
|
||||
|
||||
router.POST("/tidy", sc.TidyDB)
|
||||
}
|
|
@ -24,23 +24,28 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api-admin/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func declareZoneRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, store storage.Storage) {
|
||||
zc := controller.NewZoneController(dependancies.GetDomainService(), dependancies.GetZoneService(), store)
|
||||
zc := controller.NewZoneController(
|
||||
dependancies.DomainUsecase(),
|
||||
dependancies.ZoneUsecase(),
|
||||
dependancies.ZoneCorrectionApplierUsecase(),
|
||||
store,
|
||||
)
|
||||
|
||||
router.GET("/zones", zc.ListZones)
|
||||
router.PUT("/zones", zc.UpdateZones)
|
||||
router.POST("/zones", zc.AddZone)
|
||||
// PUT /zones is handled by DomainController
|
||||
|
||||
router.DELETE("/zones/:zoneid", zc.DeleteZone)
|
||||
|
||||
apiZonesRoutes := router.Group("/zones/:zoneid")
|
||||
apiZonesRoutes.Use(middleware.ZoneHandler(dependancies.GetZoneService()))
|
||||
apiZonesRoutes.Use(middleware.ZoneHandler(dependancies.ZoneUsecase()))
|
||||
|
||||
apiZonesRoutes.GET("", zc.GetZone)
|
||||
apiZonesRoutes.PUT("", zc.UpdateZone)
|
|
@ -29,6 +29,7 @@ import (
|
|||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -63,18 +64,7 @@ func (lc *LoginController) Login(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
session := sessions.Default(c)
|
||||
|
||||
session.Clear()
|
||||
session.Set("iduser", user.Id)
|
||||
err = session.Save()
|
||||
if err != nil {
|
||||
log.Printf("%s: unable to save user session: %s", c.ClientIP(), err.Error())
|
||||
c.JSON(http.StatusUnauthorized, happydns.ErrorResponse{Message: "Invalid username or password."})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("%s: now logged as %q\n", c.ClientIP(), user.Email)
|
||||
middleware.SessionLoginOK(c, user)
|
||||
|
||||
c.JSON(http.StatusOK, user)
|
||||
}
|
|
@ -31,6 +31,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
|
@ -38,7 +39,7 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -47,23 +48,39 @@ const (
|
|||
)
|
||||
|
||||
type OIDCProvider struct {
|
||||
config *config.Options
|
||||
config *happydns.Options
|
||||
authService happydns.AuthenticationUsecase
|
||||
oauth2config *oauth2.Config
|
||||
oidcVerifier *oidc.IDTokenVerifier
|
||||
}
|
||||
|
||||
func NewOIDCProvider(cfg *config.Options, authService happydns.AuthenticationUsecase) *OIDCProvider {
|
||||
func GetOIDCProvider(o *happydns.Options, ctx context.Context) (*oidc.Provider, error) {
|
||||
return oidc.NewProvider(ctx, strings.TrimSuffix(o.OIDCClients[0].ProviderURL.String(), "/.well-known/openid-configuration"))
|
||||
}
|
||||
|
||||
func GetOAuth2Config(o *happydns.Options, provider *oidc.Provider) *oauth2.Config {
|
||||
oauth2Config := oauth2.Config{
|
||||
ClientID: o.OIDCClients[0].ClientID,
|
||||
ClientSecret: o.OIDCClients[0].ClientSecret,
|
||||
RedirectURL: o.GetAuthURL().String(),
|
||||
Endpoint: provider.Endpoint(),
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
}
|
||||
|
||||
return &oauth2Config
|
||||
}
|
||||
|
||||
func NewOIDCProvider(cfg *happydns.Options, authService happydns.AuthenticationUsecase) *OIDCProvider {
|
||||
// Initialize OIDC
|
||||
provider, err := cfg.GetOIDCProvider(context.Background())
|
||||
provider, err := GetOIDCProvider(cfg, context.Background())
|
||||
if err != nil {
|
||||
log.Fatal("Unable to instantiate OIDC Provider:", err)
|
||||
}
|
||||
|
||||
oauth2Config := cfg.GetOAuth2Config(provider)
|
||||
oauth2Config := GetOAuth2Config(cfg, provider)
|
||||
|
||||
oidcVerifier := provider.Verifier(&oidc.Config{
|
||||
ClientID: config.OIDCClientID,
|
||||
ClientID: cfg.OIDCClients[0].ClientID,
|
||||
})
|
||||
|
||||
return &OIDCProvider{
|
||||
|
@ -87,7 +104,6 @@ func (p *OIDCProvider) RedirectOIDC(c *gin.Context) {
|
|||
|
||||
session.Set(SESSION_KEY_OIDC_STATE, hex.EncodeToString(state))
|
||||
err = session.Save()
|
||||
|
||||
if err != nil {
|
||||
log.Println("Unable to redirect_OIDC, session.Save fails:", err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, happydns.ErrorResponse{Message: "Sorry, we are currently unable to respond to your request. Please retry later."})
|
||||
|
@ -108,6 +124,14 @@ func (p *OIDCProvider) CompleteOIDC(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
session.Delete(SESSION_KEY_OIDC_STATE)
|
||||
err := session.Save()
|
||||
if err != nil {
|
||||
log.Println("Unable to CompleteOIDC, session.Save fails:", err)
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, happydns.ErrorResponse{Message: "Sorry, we are currently unable to respond to your request. Please retry later."})
|
||||
return
|
||||
}
|
||||
|
||||
oauth2Token, err := p.oauth2config.Exchange(c, c.Query("code"))
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, happydns.ErrorResponse{Message: fmt.Sprintf("Failed to exchange token: %s", err.Error())})
|
||||
|
@ -157,5 +181,7 @@ func (p *OIDCProvider) CompleteOIDC(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
middleware.SessionLoginOK(c, &profile)
|
||||
|
||||
c.Redirect(http.StatusFound, p.config.GetBaseURL()+"/")
|
||||
}
|
|
@ -29,17 +29,21 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
"github.com/miekg/dns"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type DomainController struct {
|
||||
domainService happydns.DomainUsecase
|
||||
domainService happydns.DomainUsecase
|
||||
remoteZoneImporter happydns.RemoteZoneImporterUsecase
|
||||
zoneImporter happydns.ZoneImporterUsecase
|
||||
}
|
||||
|
||||
func NewDomainController(domainService happydns.DomainUsecase) *DomainController {
|
||||
func NewDomainController(domainService happydns.DomainUsecase, remoteZoneImporter happydns.RemoteZoneImporterUsecase, zoneImporter happydns.ZoneImporterUsecase) *DomainController {
|
||||
return &DomainController{
|
||||
domainService: domainService,
|
||||
domainService: domainService,
|
||||
remoteZoneImporter: remoteZoneImporter,
|
||||
zoneImporter: zoneImporter,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +84,7 @@ func (dc *DomainController) GetDomains(c *gin.Context) {
|
|||
// @Tags domains
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body happydns.DomainMinimal true "Domain object that you want to manage through happyDomain."
|
||||
// @Param body body happydns.DomainCreationInput true "Domain object that you want to manage through happyDomain."
|
||||
// @Security securitydefinitions.basic
|
||||
// @Success 200 {object} happydns.Domain
|
||||
// @Failure 400 {object} happydns.ErrorResponse "Error in received data"
|
||||
|
@ -230,7 +234,7 @@ func (dc *DomainController) RetrieveZone(c *gin.Context) {
|
|||
}
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
|
||||
zone, err := dc.domainService.RetrieveRemoteZone(user, domain)
|
||||
zone, err := dc.remoteZoneImporter.Import(user, domain)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -263,7 +267,7 @@ func (dc *DomainController) ImportZone(c *gin.Context) {
|
|||
rrs = append(rrs, rr)
|
||||
}
|
||||
|
||||
zone, err := dc.domainService.ImportZone(user, domain, rrs)
|
||||
zone, err := dc.zoneImporter.Import(user, domain, rrs)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
|
@ -58,7 +58,7 @@ func NewDomainLogController(domainLogService happydns.DomainLogUsecase) *DomainL
|
|||
func (dlc *DomainLogController) GetDomainLogs(c *gin.Context) {
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
|
||||
logs, err := dlc.domainLogService.GetDomainLogs(domain)
|
||||
logs, err := dlc.domainLogService.ListDomainLogs(domain)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s: An error occurs in GetDomainLogs, when retrieving logs: %s", c.ClientIP(), err.Error())
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
|
@ -28,7 +28,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -67,6 +67,7 @@ func (psc *ProviderSettingsController) NextProviderSettingsState(c *gin.Context)
|
|||
}
|
||||
|
||||
specs := c.MustGet("providerspecs").(happydns.ProviderBody)
|
||||
pType := c.MustGet("providertype").(string)
|
||||
|
||||
var uss happydns.ProviderSettingsState
|
||||
uss.ProviderBody = specs
|
||||
|
@ -77,7 +78,7 @@ func (psc *ProviderSettingsController) NextProviderSettingsState(c *gin.Context)
|
|||
return
|
||||
}
|
||||
|
||||
provider, form, err := psc.pSettingsServices.NextProviderSettingsState(specs, user, &uss)
|
||||
provider, form, err := psc.pSettingsServices.NextProviderSettingsState(&uss, pType, user)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
|
@ -26,7 +26,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
|
@ -28,7 +28,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
|
@ -28,18 +28,18 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
serviceUC "git.happydns.org/happyDomain/internal/usecase/service"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/usecase"
|
||||
)
|
||||
|
||||
type ServiceController struct {
|
||||
duService happydns.DomainUsecase
|
||||
suService happydns.ServiceUsecase
|
||||
duService happydns.ZoneServiceUsecase
|
||||
zuService happydns.ZoneUsecase
|
||||
}
|
||||
|
||||
func NewServiceController(duService happydns.DomainUsecase, suService happydns.ServiceUsecase, zuService happydns.ZoneUsecase) *ServiceController {
|
||||
func NewServiceController(duService happydns.ZoneServiceUsecase, suService happydns.ServiceUsecase, zuService happydns.ZoneUsecase) *ServiceController {
|
||||
return &ServiceController{
|
||||
duService: duService,
|
||||
suService: suService,
|
||||
|
@ -68,7 +68,7 @@ func (sc *ServiceController) AddZoneService(c *gin.Context) {
|
|||
user := middleware.MyUser(c)
|
||||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
subdomain := c.MustGet("subdomain").(string)
|
||||
subdomain := c.MustGet("subdomain").(happydns.Subdomain)
|
||||
|
||||
var usc happydns.ServiceMessage
|
||||
err := c.ShouldBindJSON(&usc)
|
||||
|
@ -78,13 +78,13 @@ func (sc *ServiceController) AddZoneService(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
newservice, err := usecase.ParseService(&usc)
|
||||
newservice, err := serviceUC.ParseService(&usc)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
zone, err = sc.duService.AppendZoneService(user, domain, zone, subdomain, domain.DomainName, newservice)
|
||||
zone, err = sc.duService.AddServiceToZone(user, domain, zone, subdomain, happydns.Origin(domain.DomainName), newservice)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -113,7 +113,7 @@ func (sc *ServiceController) AddZoneService(c *gin.Context) {
|
|||
func (sc *ServiceController) GetZoneService(c *gin.Context) {
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
serviceid := c.MustGet("serviceid").(happydns.Identifier)
|
||||
subdomain := c.MustGet("subdomain").(string)
|
||||
subdomain := c.MustGet("subdomain").(happydns.Subdomain)
|
||||
|
||||
_, svc := zone.FindSubdomainService(subdomain, serviceid)
|
||||
|
||||
|
@ -141,7 +141,7 @@ func (sc *ServiceController) GetServiceRecords(c *gin.Context) {
|
|||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
serviceid := c.MustGet("serviceid").(happydns.Identifier)
|
||||
subdomain := c.MustGet("subdomain").(string)
|
||||
subdomain := c.MustGet("subdomain").(happydns.Subdomain)
|
||||
|
||||
_, svc := zone.FindSubdomainService(subdomain, serviceid)
|
||||
if svc == nil {
|
||||
|
@ -192,13 +192,13 @@ func (sc *ServiceController) UpdateZoneService(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
newservice, err := usecase.ParseService(&usc)
|
||||
newservice, err := serviceUC.ParseService(&usc)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
zone, err = sc.duService.UpdateZoneService(user, domain, zone, usc.Domain, usc.Id, newservice)
|
||||
zone, err = sc.duService.UpdateZoneService(user, domain, zone, happydns.Subdomain(usc.Domain), usc.Id, newservice)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -230,9 +230,9 @@ func (sc *ServiceController) DeleteZoneService(c *gin.Context) {
|
|||
domain := c.MustGet("domain").(*happydns.Domain)
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
serviceid := c.MustGet("serviceid").(happydns.Identifier)
|
||||
subdomain := c.MustGet("subdomain").(string)
|
||||
subdomain := c.MustGet("subdomain").(happydns.Subdomain)
|
||||
|
||||
zone, err := sc.duService.DeleteZoneService(user, domain, zone, subdomain, serviceid)
|
||||
zone, err := sc.duService.RemoveServiceFromZone(user, domain, zone, subdomain, serviceid)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
|
@ -27,7 +27,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
|
@ -29,7 +29,7 @@ import (
|
|||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -129,7 +129,7 @@ func (sc *SessionController) ClearUserSessions(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
err := sc.sessionService.ClearUserSessions(myuser)
|
||||
err := sc.sessionService.CloseUserSessions(myuser)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -157,7 +157,7 @@ func (sc *SessionController) GetSessions(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
s, err := sc.sessionService.GetUserSessions(myuser)
|
||||
s, err := sc.sessionService.ListUserSessions(myuser)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
|
@ -28,7 +28,7 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -138,14 +138,6 @@ func (rc *UserRecoveryController) ValidateUserAddress(c *gin.Context) {
|
|||
c.Status(http.StatusNoContent)
|
||||
}
|
||||
|
||||
type UploadedAccountRecovery struct {
|
||||
// Key is the secret sent by email to the user.
|
||||
Key string
|
||||
|
||||
// Password is the new password to use with this account.
|
||||
Password string
|
||||
}
|
||||
|
||||
// recoverUserAccount performs account recovery by reseting the password of the account.
|
||||
//
|
||||
// @Summary Reset password with link in email.
|
||||
|
@ -163,7 +155,7 @@ type UploadedAccountRecovery struct {
|
|||
func (rc *UserRecoveryController) RecoverUserAccount(c *gin.Context) {
|
||||
user := c.MustGet("authuser").(*happydns.UserAuth)
|
||||
|
||||
var uar UploadedAccountRecovery
|
||||
var uar happydns.AccountRecoveryForm
|
||||
err := c.ShouldBindJSON(&uar)
|
||||
if err != nil {
|
||||
log.Printf("%s sends invalid AccountRecovey JSON: %s", c.ClientIP(), err.Error())
|
||||
|
@ -171,17 +163,7 @@ func (rc *UserRecoveryController) RecoverUserAccount(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := user.CanRecoverAccount(uar.Key); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusForbidden, happydns.ErrorResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if len(uar.Password) == 0 {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, happydns.ErrorResponse{Message: "Password can't be empty!"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := rc.auService.ChangePassword(user, uar.Password); err != nil {
|
||||
if err := rc.auService.ResetPassword(user, uar); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, happydns.ErrorResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
|
@ -28,19 +28,21 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type ZoneController struct {
|
||||
domainService happydns.DomainUsecase
|
||||
zoneService happydns.ZoneUsecase
|
||||
domainService happydns.DomainUsecase
|
||||
zoneCorrectionService happydns.ZoneCorrectionApplierUsecase
|
||||
zoneService happydns.ZoneUsecase
|
||||
}
|
||||
|
||||
func NewZoneController(zoneService happydns.ZoneUsecase, domainService happydns.DomainUsecase) *ZoneController {
|
||||
func NewZoneController(zoneService happydns.ZoneUsecase, domainService happydns.DomainUsecase, zoneCorrectionService happydns.ZoneCorrectionApplierUsecase) *ZoneController {
|
||||
return &ZoneController{
|
||||
domainService: domainService,
|
||||
zoneService: zoneService,
|
||||
domainService: domainService,
|
||||
zoneCorrectionService: zoneCorrectionService,
|
||||
zoneService: zoneService,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +70,7 @@ func (zc *ZoneController) GetZone(c *gin.Context) {
|
|||
// @Router /domains/{domainId}/zone/{zoneId}/{subdomain} [get]
|
||||
func (zc *ZoneController) GetZoneSubdomain(c *gin.Context) {
|
||||
zone := c.MustGet("zone").(*happydns.Zone)
|
||||
subdomain := c.MustGet("subdomain").(string)
|
||||
subdomain := c.MustGet("subdomain").(happydns.Subdomain)
|
||||
|
||||
c.JSON(http.StatusOK, happydns.ZoneServices{
|
||||
Services: zone.Services[subdomain],
|
||||
|
@ -102,7 +104,7 @@ func (zc *ZoneController) DiffZones(c *gin.Context) {
|
|||
var corrections []*happydns.Correction
|
||||
if c.Param("oldzoneid") == "@" {
|
||||
var err error
|
||||
corrections, err = zc.zoneService.GetZoneCorrections(user, domain, newzone)
|
||||
corrections, err = zc.zoneCorrectionService.List(user, domain, newzone)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
||||
|
@ -155,7 +157,7 @@ func (zc *ZoneController) ApplyZoneCorrections(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
newZone, err := zc.domainService.ApplyZoneCorrection(user, domain, zone, &form)
|
||||
newZone, err := zc.zoneCorrectionService.Apply(user, domain, zone, &form)
|
||||
if err != nil {
|
||||
middleware.ErrorResponse(c, http.StatusInternalServerError, err)
|
||||
return
|
61
internal/api/middleware/auth_middleware.go
Normal file
61
internal/api/middleware/auth_middleware.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func AuthRequired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if _, ok := c.Get("LoggedUser"); !ok {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, happydns.ErrorResponse{Message: "Please login to access this resource.", Link: "/login"})
|
||||
return
|
||||
}
|
||||
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func SessionLoginOK(c *gin.Context, user happydns.UserInfo) error {
|
||||
session := sessions.Default(c)
|
||||
|
||||
session.Clear()
|
||||
session.Set("iduser", user.GetUserId())
|
||||
err := session.Save()
|
||||
if err != nil {
|
||||
return happydns.InternalError{
|
||||
Err: fmt.Errorf("failed to save save user session: %s", err),
|
||||
UserMessage: "Invalid username or password.",
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("%s: now logged as %q\n", c.ClientIP(), user.GetEmail())
|
||||
return nil
|
||||
}
|
|
@ -48,11 +48,19 @@ func DomainHandler(domainService happydns.DomainUsecase, allowFQDN bool) gin.Han
|
|||
return
|
||||
}
|
||||
|
||||
domain, err = domainService.GetUserDomainByFQDN(user, c.Param("domain"))
|
||||
if err != nil {
|
||||
var domains []*happydns.Domain
|
||||
domains, err = domainService.GetUserDomainByFQDN(user, c.Param("domain"))
|
||||
if err != nil || len(domains) == 0 {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found"})
|
||||
return
|
||||
}
|
||||
|
||||
if len(domains) != 1 {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "There are many domain names with this FQDN in your account, please use their ID to access it instead"})
|
||||
return
|
||||
}
|
||||
|
||||
domain = domains[0]
|
||||
} else {
|
||||
domain, err = domainService.GetUserDomain(user, dnid)
|
||||
if err != nil {
|
||||
|
@ -68,7 +76,7 @@ func DomainHandler(domainService happydns.DomainUsecase, allowFQDN bool) gin.Han
|
|||
} else if src, exists := c.Get("providermeta"); exists {
|
||||
provider = src.(*happydns.ProviderMeta)
|
||||
}
|
||||
if provider != nil && !provider.Id.Equals(domain.IdProvider) {
|
||||
if provider != nil && !provider.Id.Equals(domain.ProviderId) {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found (not child of provider)"})
|
||||
return
|
||||
}
|
63
internal/api/middleware/errors.go
Normal file
63
internal/api/middleware/errors.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2024 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func ErrorResponse(c *gin.Context, defaultStatus int, err error) {
|
||||
if ie, ok := err.(happydns.InternalError); ok {
|
||||
log.Println(ie.Error())
|
||||
|
||||
status := ie.HTTPStatus()
|
||||
if status == 0 {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(status, ie.ToErrorResponse())
|
||||
return
|
||||
} else if e, ok := err.(happydns.HTTPError); ok {
|
||||
status := e.HTTPStatus()
|
||||
if status == 0 {
|
||||
status = http.StatusInternalServerError
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(status, ie.ToErrorResponse())
|
||||
return
|
||||
} else if errors.Is(err, happydns.ErrAuthUserNotFound) || errors.Is(err, happydns.ErrDomainNotFound) || errors.Is(err, happydns.ErrDomainLogNotFound) || errors.Is(err, happydns.ErrProviderNotFound) || errors.Is(err, happydns.ErrSessionNotFound) || errors.Is(err, happydns.ErrUserNotFound) || errors.Is(err, happydns.ErrUserAlreadyExist) || errors.Is(err, happydns.ErrZoneNotFound) {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, happydns.ErrorResponse{
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.AbortWithStatusJSON(defaultStatus, happydns.ErrorResponse{
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
|
@ -39,6 +39,7 @@ func ProviderSpecsHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.Set("providertype", psid)
|
||||
c.Set("providerspecs", pbody)
|
||||
|
||||
c.Next()
|
|
@ -34,10 +34,7 @@ import (
|
|||
func ParseZoneId(c *gin.Context, paramName string) (happydns.Identifier, error) {
|
||||
zoneid, err := happydns.NewIdentifierFromString(c.Param(paramName))
|
||||
if err != nil {
|
||||
return nil, happydns.InternalError{
|
||||
Err: fmt.Errorf("bad zone identifier (%s) format: %s", paramName, err.Error()),
|
||||
HTTPStatus: http.StatusBadRequest,
|
||||
}
|
||||
return nil, happydns.ValidationError{Msg: fmt.Sprintf("bad zone identifier format (%s): %s", paramName, err.Error())}
|
||||
}
|
||||
|
||||
return zoneid, nil
|
||||
|
@ -69,7 +66,7 @@ func SubdomainHandler(c *gin.Context) {
|
|||
|
||||
subdomain := strings.TrimSuffix(strings.TrimSuffix(strings.TrimSuffix(c.Param("subdomain"), "."+domain.DomainName), "@"), domain.DomainName)
|
||||
|
||||
c.Set("subdomain", subdomain)
|
||||
c.Set("subdomain", happydns.Subdomain(subdomain))
|
||||
|
||||
c.Next()
|
||||
}
|
|
@ -26,16 +26,16 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareAuthUserRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, lc *controller.LoginController) *controller.AuthUserController {
|
||||
ac := controller.NewAuthUserController(dependancies.GetAuthUserService(), lc)
|
||||
ac := controller.NewAuthUserController(dependancies.AuthUserUsecase(), lc)
|
||||
|
||||
apiUserAuthRoutes := router.Group("/users/:uid")
|
||||
apiUserAuthRoutes.Use(middleware.AuthUserHandler(dependancies.GetAuthUserService()))
|
||||
apiUserAuthRoutes.Use(middleware.AuthUserHandler(dependancies.AuthUserUsecase()))
|
||||
apiUserAuthRoutes.GET("/is_auth_user", func(c *gin.Context) {
|
||||
c.Status(http.StatusNoContent)
|
||||
})
|
|
@ -28,23 +28,22 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareAuthenticationRoutes(cfg *config.Options, baserouter, apirouter *gin.RouterGroup, dependancies happydns.UsecaseDependancies) *controller.LoginController {
|
||||
lc := controller.NewLoginController(dependancies.GetAuthenticationService())
|
||||
func DeclareAuthenticationRoutes(cfg *happydns.Options, baserouter, apirouter *gin.RouterGroup, dependancies happydns.UsecaseDependancies) *controller.LoginController {
|
||||
lc := controller.NewLoginController(dependancies.AuthenticationUsecase())
|
||||
|
||||
apirouter.POST("/auth", lc.Login)
|
||||
apirouter.POST("/auth/logout", lc.Logout)
|
||||
|
||||
if cfg.GetOIDCProviderURL() != "" {
|
||||
oidcp := controller.NewOIDCProvider(cfg, dependancies.GetAuthenticationService())
|
||||
if len(cfg.OIDCClients) > 0 {
|
||||
oidcp := controller.NewOIDCProvider(cfg, dependancies.AuthenticationUsecase())
|
||||
|
||||
authRoutes := baserouter.Group("/auth")
|
||||
|
||||
providerurl, _ := url.Parse(cfg.GetOIDCProviderURL())
|
||||
providerurl, _ := url.Parse(cfg.OIDCClients[0].ProviderURL.String())
|
||||
authRoutes.GET("has_oidc", func(c *gin.Context) {
|
||||
parts := strings.Split(strings.TrimSuffix(providerurl.Host, "."), ".")
|
||||
if len(parts) > 2 {
|
|
@ -24,19 +24,23 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareDomainRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
dc := controller.NewDomainController(dependancies.GetDomainService())
|
||||
dc := controller.NewDomainController(
|
||||
dependancies.DomainUsecase(),
|
||||
dependancies.RemoteZoneImporterUsecase(),
|
||||
dependancies.ZoneImporterUsecase(),
|
||||
)
|
||||
|
||||
router.GET("/domains", dc.GetDomains)
|
||||
router.POST("/domains", dc.AddDomain)
|
||||
|
||||
apiDomainsRoutes := router.Group("/domains/:domain")
|
||||
apiDomainsRoutes.Use(middleware.DomainHandler(dependancies.GetDomainService(), false))
|
||||
apiDomainsRoutes.Use(middleware.DomainHandler(dependancies.DomainUsecase(), false))
|
||||
|
||||
apiDomainsRoutes.GET("", dc.GetDomain)
|
||||
apiDomainsRoutes.PUT("", dc.UpdateDomain)
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareDomainLogRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
dlc := controller.NewDomainLogController(dependancies.GetDomainLogService())
|
||||
dlc := controller.NewDomainLogController(dependancies.DomainLogUsecase())
|
||||
|
||||
router.GET("/logs", dlc.GetDomainLogs)
|
||||
}
|
|
@ -24,24 +24,24 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareProviderRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
pc := controller.NewProviderController(dependancies.GetProviderService(true))
|
||||
pc := controller.NewProviderController(dependancies.ProviderUsecase(true))
|
||||
|
||||
router.GET("/providers", pc.ListProviders)
|
||||
router.POST("/providers", pc.AddProvider)
|
||||
|
||||
apiProvidersMetaRoutes := router.Group("/providers/:pid")
|
||||
apiProvidersMetaRoutes.Use(middleware.ProviderMetaHandler(dependancies.GetProviderService(true)))
|
||||
apiProvidersMetaRoutes.Use(middleware.ProviderMetaHandler(dependancies.ProviderUsecase(true)))
|
||||
|
||||
apiProvidersMetaRoutes.DELETE("", pc.DeleteProvider)
|
||||
|
||||
apiProviderRoutes := router.Group("/providers/:pid")
|
||||
apiProviderRoutes.Use(middleware.ProviderHandler(dependancies.GetProviderService(true)))
|
||||
apiProviderRoutes.Use(middleware.ProviderHandler(dependancies.ProviderUsecase(true)))
|
||||
|
||||
apiProviderRoutes.GET("", pc.GetProvider)
|
||||
apiProviderRoutes.PUT("", pc.UpdateProvider)
|
|
@ -24,13 +24,13 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareProviderSettingsRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
psc := controller.NewProviderSettingsController(dependancies.GetProviderSettingsService())
|
||||
psc := controller.NewProviderSettingsController(dependancies.ProviderSettingsUsecase())
|
||||
|
||||
apiProviderSpecsRoutes := router.Group("/providers/_specs/:psid")
|
||||
apiProviderSpecsRoutes.Use(middleware.ProviderSpecsHandler)
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareProviderSpecsRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
pc := controller.NewProviderSpecsController(dependancies.GetProviderSpecsService())
|
||||
pc := controller.NewProviderSpecsController(dependancies.ProviderSpecsUsecase())
|
||||
|
||||
router.GET("/providers/_specs", pc.ListProviders)
|
||||
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareResolverRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
rc := controller.NewResolverController(dependancies.GetResolverService())
|
||||
rc := controller.NewResolverController(dependancies.ResolverUsecase())
|
||||
|
||||
router.POST("/resolver", rc.RunResolver)
|
||||
}
|
|
@ -24,8 +24,7 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -49,7 +48,7 @@ import (
|
|||
// @name Authorization
|
||||
// @description Description for what is this security definition being used
|
||||
|
||||
func DeclareRoutes(cfg *config.Options, router *gin.Engine, dependancies happydns.UsecaseDependancies) {
|
||||
func DeclareRoutes(cfg *happydns.Options, router *gin.Engine, dependancies happydns.UsecaseDependancies) {
|
||||
// Declare routes
|
||||
baseRoutes := router.Group("")
|
||||
|
||||
|
@ -70,10 +69,10 @@ func DeclareRoutes(cfg *config.Options, router *gin.Engine, dependancies happydn
|
|||
apiAuthRoutes := router.Group("/api")
|
||||
|
||||
if cfg.NoAuth {
|
||||
apiAuthRoutes.Use(middleware.NoAuthMiddleware(dependancies.GetAuthenticationService()))
|
||||
apiAuthRoutes.Use(middleware.NoAuthMiddleware(dependancies.AuthenticationUsecase()))
|
||||
} else {
|
||||
apiAuthRoutes.Use(middleware.JwtAuthMiddleware(dependancies.GetAuthenticationService(), cfg.JWTSigningMethod, cfg.JWTSecretKey))
|
||||
apiAuthRoutes.Use(middleware.SessionMiddleware(dependancies.GetAuthenticationService()))
|
||||
apiAuthRoutes.Use(middleware.JwtAuthMiddleware(dependancies.AuthenticationUsecase(), cfg.JWTSigningMethod, cfg.JWTSecretKey))
|
||||
apiAuthRoutes.Use(middleware.SessionMiddleware(dependancies.AuthenticationUsecase()))
|
||||
}
|
||||
apiAuthRoutes.Use(middleware.AuthRequired())
|
||||
|
|
@ -24,20 +24,20 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareZoneServiceRoutes(apiZonesRoutes, apiZonesSubdomainRoutes *gin.RouterGroup, zc *controller.ZoneController, dependancies happydns.UsecaseDependancies) {
|
||||
sc := controller.NewServiceController(dependancies.GetDomainService(), dependancies.GetServiceService(), dependancies.GetZoneService())
|
||||
sc := controller.NewServiceController(dependancies.ZoneServiceUsecase(), dependancies.ServiceUsecase(), dependancies.ZoneUsecase())
|
||||
|
||||
apiZonesRoutes.PATCH("", sc.UpdateZoneService)
|
||||
|
||||
apiZonesSubdomainRoutes.POST("/services", sc.AddZoneService)
|
||||
|
||||
apiZonesSubdomainServiceIdRoutes := apiZonesSubdomainRoutes.Group("/services/:serviceid")
|
||||
apiZonesSubdomainServiceIdRoutes.Use(middleware.ServiceIdHandler(dependancies.GetServiceService()))
|
||||
apiZonesSubdomainServiceIdRoutes.Use(middleware.ServiceIdHandler(dependancies.ServiceUsecase()))
|
||||
apiZonesSubdomainServiceIdRoutes.GET("", sc.GetZoneService)
|
||||
apiZonesSubdomainServiceIdRoutes.DELETE("", sc.DeleteZoneService)
|
||||
|
|
@ -24,13 +24,13 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareServiceSpecsRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
ssc := controller.NewServiceSpecsController(dependancies.GetServiceSpecsService())
|
||||
ssc := controller.NewServiceSpecsController(dependancies.ServiceSpecsUsecase())
|
||||
|
||||
router.GET("/service_specs", ssc.ListServiceSpecs)
|
||||
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareSessionRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
sc := controller.NewSessionController(dependancies.GetSessionService())
|
||||
sc := controller.NewSessionController(dependancies.SessionUsecase())
|
||||
|
||||
router.GET("/session", sc.GetSession)
|
||||
router.DELETE("/session", sc.ClearSession)
|
|
@ -24,22 +24,22 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareUsersRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, lc *controller.LoginController) *controller.UserController {
|
||||
uc := controller.NewUserController(dependancies.GetUserService(), lc)
|
||||
uc := controller.NewUserController(dependancies.UserUsecase(), lc)
|
||||
|
||||
apiUserRoutes := router.Group("/users/:uid")
|
||||
apiUserRoutes.Use(middleware.UserHandler(dependancies.GetUserService()))
|
||||
apiUserRoutes.Use(middleware.UserHandler(dependancies.UserUsecase()))
|
||||
|
||||
apiUserRoutes.GET("", uc.GetUser)
|
||||
apiUserRoutes.GET("/avatar.png", uc.GetUserAvatar)
|
||||
|
||||
apiSameUserRoutes := router.Group("/users/:uid")
|
||||
apiSameUserRoutes.Use(middleware.UserHandler(dependancies.GetUserService()))
|
||||
apiSameUserRoutes.Use(middleware.UserHandler(dependancies.UserUsecase()))
|
||||
apiSameUserRoutes.Use(middleware.SameUserHandler)
|
||||
|
||||
apiSameUserRoutes.DELETE("", uc.DeleteMyUser)
|
|
@ -24,18 +24,18 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareUserRecoveryRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies, auc *controller.AuthUserController) *controller.UserRecoveryController {
|
||||
urc := controller.NewUserRecoveryController(dependancies.GetAuthUserService())
|
||||
urc := controller.NewUserRecoveryController(dependancies.AuthUserUsecase())
|
||||
|
||||
router.PATCH("/users", urc.UserRecoveryOperations)
|
||||
|
||||
apiUserRoutes := router.Group("/users/:uid")
|
||||
apiUserRoutes.Use(middleware.AuthUserHandler(dependancies.GetAuthUserService()))
|
||||
apiUserRoutes.Use(middleware.AuthUserHandler(dependancies.AuthUserUsecase()))
|
||||
|
||||
apiUserRoutes.POST("/email", urc.ValidateUserAddress)
|
||||
apiUserRoutes.POST("/recovery", urc.RecoverUserAccount)
|
|
@ -24,12 +24,12 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareRegistrationRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) *controller.RegistrationController {
|
||||
rc := controller.NewRegistrationController(dependancies.GetAuthUserService())
|
||||
rc := controller.NewRegistrationController(dependancies.AuthUserUsecase())
|
||||
|
||||
router.POST("/users", rc.RegisterNewUser)
|
||||
|
|
@ -24,7 +24,7 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
)
|
||||
|
||||
func DeclareVersionRoutes(router *gin.RouterGroup) {
|
|
@ -24,16 +24,20 @@ package route
|
|||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/api/middleware"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/api/middleware"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func DeclareZoneRoutes(router *gin.RouterGroup, dependancies happydns.UsecaseDependancies) {
|
||||
zc := controller.NewZoneController(dependancies.GetZoneService(), dependancies.GetDomainService())
|
||||
zc := controller.NewZoneController(
|
||||
dependancies.ZoneUsecase(),
|
||||
dependancies.DomainUsecase(),
|
||||
dependancies.ZoneCorrectionApplierUsecase(),
|
||||
)
|
||||
|
||||
apiZonesRoutes := router.Group("/zone/:zoneid")
|
||||
apiZonesRoutes.Use(middleware.ZoneHandler(dependancies.GetZoneService()))
|
||||
apiZonesRoutes.Use(middleware.ZoneHandler(dependancies.ZoneUsecase()))
|
||||
|
||||
apiZonesRoutes.GET("", zc.GetZone)
|
||||
|
|
@ -32,14 +32,14 @@ import (
|
|||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
admin "git.happydns.org/happyDomain/api-admin/route"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/usecase"
|
||||
admin "git.happydns.org/happyDomain/internal/api-admin/route"
|
||||
providerUC "git.happydns.org/happyDomain/internal/usecase/provider"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
type Admin struct {
|
||||
router *gin.Engine
|
||||
cfg *config.Options
|
||||
cfg *happydns.Options
|
||||
srv *http.Server
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ func NewAdmin(app *App) *Admin {
|
|||
router.Use(gin.Logger(), gin.Recovery())
|
||||
|
||||
// Prepare usecases
|
||||
app.ProviderServiceAdmin = usecase.NewAdminProviderUsecase(app.store)
|
||||
app.usecases.providerAdmin = providerUC.NewProviderUsecases(app.store)
|
||||
|
||||
admin.DeclareRoutes(app.cfg, router, app.store, app)
|
||||
|
||||
|
|
|
@ -30,123 +30,183 @@ import (
|
|||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
api "git.happydns.org/happyDomain/api/route"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
api "git.happydns.org/happyDomain/internal/api/route"
|
||||
"git.happydns.org/happyDomain/internal/mailer"
|
||||
"git.happydns.org/happyDomain/internal/newsletter"
|
||||
"git.happydns.org/happyDomain/internal/session"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/internal/usecase"
|
||||
authuserUC "git.happydns.org/happyDomain/internal/usecase/authuser"
|
||||
domainUC "git.happydns.org/happyDomain/internal/usecase/domain"
|
||||
domainlogUC "git.happydns.org/happyDomain/internal/usecase/domain_log"
|
||||
"git.happydns.org/happyDomain/internal/usecase/orchestrator"
|
||||
providerUC "git.happydns.org/happyDomain/internal/usecase/provider"
|
||||
serviceUC "git.happydns.org/happyDomain/internal/usecase/service"
|
||||
sessionUC "git.happydns.org/happyDomain/internal/usecase/session"
|
||||
userUC "git.happydns.org/happyDomain/internal/usecase/user"
|
||||
zoneUC "git.happydns.org/happyDomain/internal/usecase/zone"
|
||||
zoneServiceUC "git.happydns.org/happyDomain/internal/usecase/zone_service"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
"git.happydns.org/happyDomain/ui"
|
||||
"git.happydns.org/happyDomain/usecase"
|
||||
"git.happydns.org/happyDomain/web"
|
||||
)
|
||||
|
||||
type Usecases struct {
|
||||
authentication happydns.AuthenticationUsecase
|
||||
authUser happydns.AuthUserUsecase
|
||||
domain happydns.DomainUsecase
|
||||
domainLog happydns.DomainLogUsecase
|
||||
provider happydns.ProviderUsecase
|
||||
providerAdmin happydns.ProviderUsecase
|
||||
providerSpecs happydns.ProviderSpecsUsecase
|
||||
providerSettings happydns.ProviderSettingsUsecase
|
||||
resolver happydns.ResolverUsecase
|
||||
session happydns.SessionUsecase
|
||||
service happydns.ServiceUsecase
|
||||
serviceSpecs happydns.ServiceSpecsUsecase
|
||||
user happydns.UserUsecase
|
||||
zone happydns.ZoneUsecase
|
||||
zoneService happydns.ZoneServiceUsecase
|
||||
|
||||
orchestrator *orchestrator.Orchestrator
|
||||
}
|
||||
|
||||
type App struct {
|
||||
cfg *config.Options
|
||||
mailer *mailer.Mailer
|
||||
router *gin.Engine
|
||||
srv *http.Server
|
||||
insights *insightsCollector
|
||||
store storage.Storage
|
||||
|
||||
AuthenticationService happydns.AuthenticationUsecase
|
||||
AuthUserService happydns.AuthUserUsecase
|
||||
DomainService happydns.DomainUsecase
|
||||
DomainLogService happydns.DomainLogUsecase
|
||||
ProviderService happydns.ProviderUsecase
|
||||
ProviderServiceAdmin happydns.ProviderUsecase
|
||||
ProviderSpecsService happydns.ProviderSpecsUsecase
|
||||
ProviderSettingsService happydns.ProviderSettingsUsecase
|
||||
ResolverService happydns.ResolverUsecase
|
||||
SessionService happydns.SessionUsecase
|
||||
ServiceService happydns.ServiceUsecase
|
||||
ServiceSpecsService happydns.ServiceSpecsUsecase
|
||||
UserService happydns.UserUsecase
|
||||
ZoneService happydns.ZoneUsecase
|
||||
cfg *happydns.Options
|
||||
mailer *mailer.Mailer
|
||||
newsletter happydns.NewsletterSubscriptor
|
||||
router *gin.Engine
|
||||
srv *http.Server
|
||||
insights *insightsCollector
|
||||
store storage.Storage
|
||||
usecases Usecases
|
||||
}
|
||||
|
||||
func (a *App) GetAuthenticationService() happydns.AuthenticationUsecase {
|
||||
return a.AuthenticationService
|
||||
func (a *App) AuthenticationUsecase() happydns.AuthenticationUsecase {
|
||||
return a.usecases.authentication
|
||||
}
|
||||
|
||||
func (a *App) GetAuthUserService() happydns.AuthUserUsecase {
|
||||
return a.AuthUserService
|
||||
func (a *App) AuthUserUsecase() happydns.AuthUserUsecase {
|
||||
return a.usecases.authUser
|
||||
}
|
||||
|
||||
func (a *App) GetDomainService() happydns.DomainUsecase {
|
||||
return a.DomainService
|
||||
func (a *App) DomainUsecase() happydns.DomainUsecase {
|
||||
return a.usecases.domain
|
||||
}
|
||||
|
||||
func (a *App) GetDomainLogService() happydns.DomainLogUsecase {
|
||||
return a.DomainLogService
|
||||
func (a *App) DomainLogUsecase() happydns.DomainLogUsecase {
|
||||
return a.usecases.domainLog
|
||||
}
|
||||
|
||||
func (a *App) GetProviderService(secure bool) happydns.ProviderUsecase {
|
||||
func (a *App) Orchestrator() *orchestrator.Orchestrator {
|
||||
return a.usecases.orchestrator
|
||||
}
|
||||
|
||||
func (a *App) ProviderUsecase(secure bool) happydns.ProviderUsecase {
|
||||
if secure {
|
||||
return a.ProviderService
|
||||
return a.usecases.provider
|
||||
} else {
|
||||
return a.ProviderServiceAdmin
|
||||
return a.usecases.providerAdmin
|
||||
}
|
||||
}
|
||||
|
||||
func (a *App) GetProviderSettingsService() happydns.ProviderSettingsUsecase {
|
||||
return a.ProviderSettingsService
|
||||
func (a *App) ProviderSettingsUsecase() happydns.ProviderSettingsUsecase {
|
||||
return a.usecases.providerSettings
|
||||
}
|
||||
|
||||
func (a *App) GetProviderSpecsService() happydns.ProviderSpecsUsecase {
|
||||
return a.ProviderSpecsService
|
||||
func (a *App) ProviderSpecsUsecase() happydns.ProviderSpecsUsecase {
|
||||
return a.usecases.providerSpecs
|
||||
}
|
||||
|
||||
func (a *App) GetResolverService() happydns.ResolverUsecase {
|
||||
return a.ResolverService
|
||||
func (a *App) ResolverUsecase() happydns.ResolverUsecase {
|
||||
return a.usecases.resolver
|
||||
}
|
||||
|
||||
func (a *App) GetServiceService() happydns.ServiceUsecase {
|
||||
return a.ServiceService
|
||||
func (a *App) RemoteZoneImporterUsecase() happydns.RemoteZoneImporterUsecase {
|
||||
return a.usecases.orchestrator.RemoteZoneImporter
|
||||
}
|
||||
|
||||
func (a *App) GetServiceSpecsService() happydns.ServiceSpecsUsecase {
|
||||
return a.ServiceSpecsService
|
||||
func (a *App) ServiceUsecase() happydns.ServiceUsecase {
|
||||
return a.usecases.service
|
||||
}
|
||||
|
||||
func (a *App) GetSessionService() happydns.SessionUsecase {
|
||||
return a.SessionService
|
||||
func (a *App) ServiceSpecsUsecase() happydns.ServiceSpecsUsecase {
|
||||
return a.usecases.serviceSpecs
|
||||
}
|
||||
|
||||
func (a *App) GetUserService() happydns.UserUsecase {
|
||||
return a.UserService
|
||||
func (a *App) SessionUsecase() happydns.SessionUsecase {
|
||||
return a.usecases.session
|
||||
}
|
||||
|
||||
func (a *App) GetZoneService() happydns.ZoneUsecase {
|
||||
return a.ZoneService
|
||||
func (a *App) UserUsecase() happydns.UserUsecase {
|
||||
return a.usecases.user
|
||||
}
|
||||
|
||||
func NewApp(cfg *config.Options) *App {
|
||||
func (a *App) ZoneCorrectionApplierUsecase() happydns.ZoneCorrectionApplierUsecase {
|
||||
return a.usecases.orchestrator.ZoneCorrectionApplier
|
||||
}
|
||||
|
||||
func (a *App) ZoneImporterUsecase() happydns.ZoneImporterUsecase {
|
||||
return a.usecases.orchestrator.ZoneImporter
|
||||
}
|
||||
|
||||
func (a *App) ZoneUsecase() happydns.ZoneUsecase {
|
||||
return a.usecases.zone
|
||||
}
|
||||
|
||||
func (a *App) ZoneServiceUsecase() happydns.ZoneServiceUsecase {
|
||||
return a.usecases.zoneService
|
||||
}
|
||||
|
||||
func NewApp(cfg *happydns.Options) *App {
|
||||
app := &App{
|
||||
cfg: cfg,
|
||||
}
|
||||
|
||||
// Initialize mailer
|
||||
if cfg.MailSMTPHost != "" {
|
||||
app.initMailer()
|
||||
app.initStorageEngine()
|
||||
app.initNewsletter()
|
||||
app.initInsights()
|
||||
app.initUsecases()
|
||||
app.setupRouter()
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func NewAppWithStorage(cfg *happydns.Options, store storage.Storage) *App {
|
||||
app := &App{
|
||||
cfg: cfg,
|
||||
store: store,
|
||||
}
|
||||
|
||||
app.initMailer()
|
||||
app.initNewsletter()
|
||||
app.initUsecases()
|
||||
app.setupRouter()
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func (app *App) initMailer() {
|
||||
if app.cfg.MailSMTPHost != "" {
|
||||
app.mailer = &mailer.Mailer{
|
||||
MailFrom: &cfg.MailFrom,
|
||||
SendMethod: mailer.NewSMTPMailer(cfg.MailSMTPHost, cfg.MailSMTPPort, cfg.MailSMTPUsername, cfg.MailSMTPPassword),
|
||||
MailFrom: &app.cfg.MailFrom,
|
||||
SendMethod: mailer.NewSMTPMailer(app.cfg.MailSMTPHost, app.cfg.MailSMTPPort, app.cfg.MailSMTPUsername, app.cfg.MailSMTPPassword),
|
||||
}
|
||||
|
||||
if cfg.MailSMTPTLSSNoVerify {
|
||||
if app.cfg.MailSMTPTLSSNoVerify {
|
||||
app.mailer.SendMethod.(*mailer.SMTPMailer).WithTLSNoVerify()
|
||||
}
|
||||
|
||||
} else if !cfg.NoMail {
|
||||
} else if !app.cfg.NoMail {
|
||||
app.mailer = &mailer.Mailer{
|
||||
MailFrom: &cfg.MailFrom,
|
||||
MailFrom: &app.cfg.MailFrom,
|
||||
SendMethod: &mailer.SystemSendmail{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize storage
|
||||
if s, ok := storage.StorageEngines[cfg.StorageEngine]; !ok {
|
||||
log.Fatalf("Nonexistent storage engine: %q, please select one of: %v", cfg.StorageEngine, storage.GetStorageEngines())
|
||||
func (app *App) initStorageEngine() {
|
||||
if s, ok := storage.StorageEngines[app.cfg.StorageEngine]; !ok {
|
||||
log.Fatalf("Nonexistent storage engine: %q, please select one of: %v", app.cfg.StorageEngine, storage.GetStorageEngines())
|
||||
} else {
|
||||
var err error
|
||||
log.Println("Opening database...")
|
||||
|
@ -156,48 +216,73 @@ func NewApp(cfg *config.Options) *App {
|
|||
}
|
||||
|
||||
log.Println("Performing database migrations...")
|
||||
if err = app.store.DoMigration(); err != nil {
|
||||
if err = app.store.MigrateSchema(); err != nil {
|
||||
log.Fatal("Could not migrate database: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize newsletter registration
|
||||
var ns happydns.NewsletterSubscriptor
|
||||
if cfg.ListmonkURL.URL != nil {
|
||||
ns = &newsletter.ListmonkNewsletterSubscription{
|
||||
ListmonkURL: cfg.ListmonkURL.URL,
|
||||
ListmonkId: cfg.ListmonkId,
|
||||
func (app *App) initNewsletter() {
|
||||
if app.cfg.ListmonkURL.String() != "" {
|
||||
app.newsletter = &newsletter.ListmonkNewsletterSubscription{
|
||||
ListmonkURL: &app.cfg.ListmonkURL,
|
||||
ListmonkId: app.cfg.ListmonkId,
|
||||
}
|
||||
} else {
|
||||
ns = &newsletter.DummyNewsletterSubscription{}
|
||||
app.newsletter = &newsletter.DummyNewsletterSubscription{}
|
||||
}
|
||||
}
|
||||
|
||||
if !cfg.OptOutInsights {
|
||||
func (app *App) initInsights() {
|
||||
if !app.cfg.OptOutInsights {
|
||||
app.insights = &insightsCollector{
|
||||
cfg: app.cfg,
|
||||
store: app.store,
|
||||
stop: make(chan bool),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare usecases
|
||||
app.ProviderSpecsService = usecase.NewProviderSpecsUsecase()
|
||||
app.ProviderSettingsService = usecase.NewProviderSettingsUsecase(cfg, app.store)
|
||||
app.ProviderService = usecase.NewProviderUsecase(cfg, app.store)
|
||||
app.ServiceService = usecase.NewServiceUsecase()
|
||||
app.ServiceSpecsService = usecase.NewServiceSpecsUsecase()
|
||||
app.ZoneService = usecase.NewZoneUsecase(app.ProviderService, app.ServiceService, app.store)
|
||||
app.DomainLogService = usecase.NewDomainLogUsecase(app.store)
|
||||
app.DomainService = usecase.NewDomainUsecase(app.store, app.DomainLogService, app.ProviderService, app.ZoneService)
|
||||
func (app *App) initUsecases() {
|
||||
sessionService := sessionUC.NewSessionUsecases(app.store)
|
||||
authUserService := authuserUC.NewAuthUserUsecases(app.cfg, app.mailer, app.store, sessionService.CloseUserSessionsUC)
|
||||
domainLogService := domainlogUC.NewDomainLogUsecases(app.store)
|
||||
providerService := providerUC.NewRestrictedProviderUsecases(app.cfg, app.store)
|
||||
serviceService := serviceUC.NewServiceUsecases()
|
||||
zoneService := zoneUC.NewZoneUsecases(app.store)
|
||||
|
||||
app.UserService = usecase.NewUserUsecase(app.store, ns)
|
||||
app.AuthenticationService = usecase.NewAuthenticationUsecase(cfg, app.store, app.UserService)
|
||||
app.AuthUserService = usecase.NewAuthUserUsecase(cfg, app.mailer, app.store)
|
||||
app.ResolverService = usecase.NewResolverUsecase(cfg)
|
||||
app.SessionService = usecase.NewSessionUsecase(app.store)
|
||||
app.usecases.providerSpecs = usecase.NewProviderSpecsUsecase()
|
||||
app.usecases.provider = providerService
|
||||
app.usecases.providerSettings = usecase.NewProviderSettingsUsecase(app.cfg, app.usecases.provider, app.store)
|
||||
app.usecases.service = serviceService
|
||||
app.usecases.serviceSpecs = usecase.NewServiceSpecsUsecase()
|
||||
app.usecases.zone = zoneService
|
||||
app.usecases.domainLog = domainLogService
|
||||
|
||||
// Initialize router
|
||||
if cfg.DevProxy == "" {
|
||||
domainService := domainUC.NewDomainUsecases(app.store, providerService.GetProviderUC, zoneService.GetZoneUC, providerService.DomainExistenceUC, domainLogService.CreateDomainLogUC)
|
||||
app.usecases.domain = domainService
|
||||
app.usecases.zoneService = zoneServiceUC.NewZoneServiceUsecases(domainService.UpdateDomainUC, zoneService.CreateZoneUC, serviceService.ValidateServiceUC, app.store)
|
||||
|
||||
app.usecases.user = userUC.NewUserUsecases(app.store, app.newsletter, authUserService.GetAuthUserUC, sessionService.CloseUserSessionsUC)
|
||||
app.usecases.authentication = usecase.NewAuthenticationUsecase(app.cfg, app.store, app.usecases.user)
|
||||
app.usecases.authUser = authUserService
|
||||
app.usecases.resolver = usecase.NewResolverUsecase(app.cfg)
|
||||
app.usecases.session = sessionService
|
||||
|
||||
app.usecases.orchestrator = orchestrator.NewOrchestrator(
|
||||
domainLogService.CreateDomainLogUC,
|
||||
domainService.UpdateDomainUC,
|
||||
providerService.GetProviderUC,
|
||||
zoneService.ListRecordsUC,
|
||||
providerService.ZoneCorrectionsUC,
|
||||
zoneService.CreateZoneUC,
|
||||
providerService.RetrieveZoneUC,
|
||||
zoneService.UpdateZoneUC,
|
||||
)
|
||||
}
|
||||
|
||||
func (app *App) setupRouter() {
|
||||
if app.cfg.DevProxy == "" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
|
@ -205,13 +290,11 @@ func NewApp(cfg *config.Options) *App {
|
|||
app.router = gin.New()
|
||||
app.router.Use(gin.Logger(), gin.Recovery(), sessions.Sessions(
|
||||
session.COOKIE_NAME,
|
||||
session.NewSessionStore(cfg, app.store, []byte(cfg.JWTSecretKey)),
|
||||
session.NewSessionStore(app.cfg, app.store, []byte(app.cfg.JWTSecretKey)),
|
||||
))
|
||||
|
||||
api.DeclareRoutes(cfg, app.router, app)
|
||||
ui.DeclareRoutes(cfg, app.router)
|
||||
|
||||
return app
|
||||
api.DeclareRoutes(app.cfg, app.router, app)
|
||||
web.DeclareRoutes(app.cfg, app.router)
|
||||
}
|
||||
|
||||
func (app *App) Start() {
|
||||
|
|
|
@ -33,8 +33,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"git.happydns.org/happyDomain/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/api/controller"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
@ -45,7 +44,7 @@ const (
|
|||
)
|
||||
|
||||
type insightsCollector struct {
|
||||
cfg *config.Options
|
||||
cfg *happydns.Options
|
||||
store storage.Storage
|
||||
stop chan bool
|
||||
}
|
||||
|
@ -117,11 +116,12 @@ func (c *insightsCollector) collect() (*happydns.Insights, error) {
|
|||
data.Config.DisableEmbeddedLogin = c.cfg.DisableEmbeddedLogin
|
||||
data.Config.DisableProviders = c.cfg.DisableProviders
|
||||
data.Config.DisableRegistration = c.cfg.DisableRegistration
|
||||
data.Config.HasBaseURL = c.cfg.GetBasePath() != ""
|
||||
data.Config.HasBaseURL = c.cfg.BasePath != ""
|
||||
data.Config.HasDevProxy = c.cfg.DevProxy != ""
|
||||
data.Config.HasExternalAuth = c.cfg.ExternalAuth.String() != ""
|
||||
data.Config.HasListmonkURL = c.cfg.ListmonkURL.String() != ""
|
||||
data.Config.LocalBind = strings.HasPrefix(c.cfg.Bind, "127.0.0.1:") || strings.HasPrefix(c.cfg.Bind, "[::1]:")
|
||||
data.Config.NbOidcProviders = len(c.cfg.OIDCClients)
|
||||
data.Config.NoAuthActive = c.cfg.NoAuth
|
||||
data.Config.NoMail = c.cfg.NoMail
|
||||
data.Config.NonUnixAdminBind = strings.Contains(c.cfg.AdminBind, ":")
|
||||
|
@ -130,28 +130,32 @@ func (c *insightsCollector) collect() (*happydns.Insights, error) {
|
|||
// Database info
|
||||
data.Database.Version = c.store.SchemaVersion()
|
||||
|
||||
if authusers, err := c.store.GetAuthUsers(); err != nil {
|
||||
if authusers, err := c.store.ListAllAuthUsers(); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
data.Database.NbAuthUsers = len(authusers)
|
||||
for authusers.Next() {
|
||||
data.Database.NbAuthUsers++
|
||||
}
|
||||
}
|
||||
|
||||
users, err := c.store.GetUsers()
|
||||
users, err := c.store.ListAllUsers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
data.Database.NbUsers = len(users)
|
||||
}
|
||||
|
||||
data.Database.Providers = map[string]int{}
|
||||
for _, user := range users {
|
||||
for users.Next() {
|
||||
data.Database.NbUsers++
|
||||
|
||||
user := users.Item()
|
||||
|
||||
if providers, err := c.store.ListProviders(user); err == nil {
|
||||
for _, provider := range providers {
|
||||
data.Database.Providers[provider.Type] += 1
|
||||
}
|
||||
}
|
||||
|
||||
if domains, err := c.store.GetDomains(user); err == nil {
|
||||
if domains, err := c.store.ListDomains(user); err == nil {
|
||||
data.Database.NbDomains += len(domains)
|
||||
|
||||
for _, domain := range domains {
|
||||
|
|
|
@ -26,26 +26,27 @@ import (
|
|||
"fmt"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
// declareFlags registers flags for the structure Options.
|
||||
func (o *Options) declareFlags() {
|
||||
func declareFlags(o *happydns.Options) {
|
||||
flag.StringVar(&o.DevProxy, "dev", o.DevProxy, "Proxify traffic to this host for static assets")
|
||||
flag.StringVar(&o.AdminBind, "admin-bind", o.AdminBind, "Bind port/socket for administration interface")
|
||||
flag.StringVar(&o.Bind, "bind", ":8081", "Bind port/socket")
|
||||
flag.BoolVar(&o.DisableProviders, "disable-providers-edit", o.DisableProviders, "Disallow all actions on provider (add/edit/delete)")
|
||||
flag.BoolVar(&o.DisableRegistration, "disable-registration", o.DisableRegistration, "Forbids new account creation through public form/API (still allow registration from external services)")
|
||||
flag.BoolVar(&o.DisableEmbeddedLogin, "disable-embedded-login", o.DisableEmbeddedLogin, "Disables the internal user/password login in favor of external-auth or OIDC")
|
||||
flag.Var(&o.ExternalURL, "externalurl", "Begining of the URL, before the base, that should be used eg. in mails")
|
||||
flag.StringVar(&o.baseURL, "baseurl", o.baseURL, "URL prepended to each URL")
|
||||
flag.Var(&URL{&o.ExternalURL}, "externalurl", "Begining of the URL, before the base, that should be used eg. in mails")
|
||||
flag.StringVar(&o.BasePath, "baseurl", o.BasePath, "URL prepended to each URL")
|
||||
flag.StringVar(&o.DefaultNameServer, "default-ns", o.DefaultNameServer, "Adress to the default name server")
|
||||
flag.Var(&o.StorageEngine, "storage-engine", fmt.Sprintf("Select the storage engine between %v", storage.GetStorageEngines()))
|
||||
flag.StringVar(&o.StorageEngine, "storage-engine", o.StorageEngine, fmt.Sprintf("Select the storage engine between %v", storage.GetStorageEngines()))
|
||||
flag.BoolVar(&o.NoAuth, "no-auth", false, "Disable user access control, use default account")
|
||||
flag.Var(&o.JWTSecretKey, "jwt-secret-key", "Secret key used to verify JWT authentication tokens (a random secret is used if undefined)")
|
||||
flag.Var(&o.ExternalAuth, "external-auth", "Base URL to use for login and registration (use embedded forms if left empty)")
|
||||
flag.Var(&JWTSecretKey{&o.JWTSecretKey}, "jwt-secret-key", "Secret key used to verify JWT authentication tokens (a random secret is used if undefined)")
|
||||
flag.Var(&URL{&o.ExternalAuth}, "external-auth", "Base URL to use for login and registration (use embedded forms if left empty)")
|
||||
flag.BoolVar(&o.OptOutInsights, "opt-out-insights", false, "Disable the anonymous usage statistics report. If you care about this project and don't participate in discussions, don't opt-out.")
|
||||
|
||||
flag.Var(&o.ListmonkURL, "newsletter-server-url", "Base URL of the listmonk newsletter server")
|
||||
flag.Var(&URL{&o.ListmonkURL}, "newsletter-server-url", "Base URL of the listmonk newsletter server")
|
||||
flag.IntVar(&o.ListmonkId, "newsletter-id", 1, "Listmonk identifier of the list receiving the new user")
|
||||
|
||||
flag.BoolVar(&o.NoMail, "no-mail", o.NoMail, "Disable all automatic mails, skip email verification at registration")
|
||||
|
@ -60,11 +61,11 @@ func (o *Options) declareFlags() {
|
|||
}
|
||||
|
||||
// parseCLI parse the flags and treats extra args as configuration filename.
|
||||
func (o *Options) parseCLI() error {
|
||||
func parseCLI(o *happydns.Options) error {
|
||||
flag.Parse()
|
||||
|
||||
for _, conf := range flag.Args() {
|
||||
err := o.parseFile(conf)
|
||||
err := parseFile(o, conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -32,104 +32,30 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
// Options stores the configuration of the software.
|
||||
type Options struct {
|
||||
// AdminBind is the address:port or unix socket used to serve the admin
|
||||
// API.
|
||||
AdminBind string
|
||||
|
||||
// Bind is the address:port used to bind the main interface with API.
|
||||
Bind string
|
||||
|
||||
// BaseURL is the relative path where begins the root of the app.
|
||||
baseURL string
|
||||
|
||||
// DevProxy is the URL that override static assets.
|
||||
DevProxy string
|
||||
|
||||
// DefaultNameServer is the NS server suggested by default.
|
||||
DefaultNameServer string
|
||||
|
||||
// DisableProviders should disallow all actions on provider (add/edit/delete) through public API.
|
||||
DisableProviders bool
|
||||
|
||||
// DisableRegistration forbids all new registration using the public form/API.
|
||||
DisableRegistration bool
|
||||
|
||||
// DisableEmbeddedLogin disables the internal user/password login in favor of ExternalAuth or OIDC.
|
||||
DisableEmbeddedLogin bool
|
||||
|
||||
// ExternalAuth is the URL of the login form to use instead of the embedded one.
|
||||
ExternalAuth URL
|
||||
|
||||
// ExternalURL keeps the URL used in communications (such as email,
|
||||
// ...), when it needs to use complete URL, not only relative parts.
|
||||
ExternalURL URL
|
||||
|
||||
// JWTSecretKey stores the private key to sign and verify JWT tokens.
|
||||
JWTSecretKey JWTSecretKey
|
||||
|
||||
// JWTSigningMethod is the signing method to check token signature.
|
||||
JWTSigningMethod string
|
||||
|
||||
// NoAuth controls if there is user access control or not.
|
||||
NoAuth bool
|
||||
|
||||
// OptOutInsights disable the anonymous usage statistics report.
|
||||
OptOutInsights bool
|
||||
|
||||
// StorageEngine points to the storage engine used.
|
||||
StorageEngine storage.StorageEngine
|
||||
|
||||
ListmonkURL URL
|
||||
ListmonkId int
|
||||
|
||||
// MailFrom holds the content of the From field for all e-mails that
|
||||
// will be send.
|
||||
MailFrom mail.Address
|
||||
|
||||
NoMail bool
|
||||
MailSMTPHost string
|
||||
MailSMTPPort uint
|
||||
MailSMTPUsername string
|
||||
MailSMTPPassword string
|
||||
MailSMTPTLSSNoVerify bool
|
||||
}
|
||||
|
||||
// GetBaseURL returns the full url to the absolute ExternalURL, including BaseURL.
|
||||
func (o *Options) GetBaseURL() string {
|
||||
return fmt.Sprintf("%s%s", o.ExternalURL.URL.String(), o.baseURL)
|
||||
}
|
||||
|
||||
// GetBasePath returns the baseURL.
|
||||
func (o *Options) GetBasePath() string {
|
||||
return o.baseURL
|
||||
}
|
||||
|
||||
// ConsolidateConfig fills an Options struct by reading configuration from
|
||||
// config files, environment, then command line.
|
||||
//
|
||||
// Should be called only one time.
|
||||
func ConsolidateConfig() (opts *Options, err error) {
|
||||
func ConsolidateConfig() (opts *happydns.Options, err error) {
|
||||
u, _ := url.Parse("http://localhost:8081")
|
||||
|
||||
// Define defaults options
|
||||
opts = &Options{
|
||||
opts = &happydns.Options{
|
||||
AdminBind: "./happydomain.sock",
|
||||
baseURL: "/",
|
||||
BasePath: "/",
|
||||
Bind: ":8081",
|
||||
DefaultNameServer: "127.0.0.1:53",
|
||||
ExternalURL: URL{URL: u},
|
||||
ExternalURL: *u,
|
||||
JWTSigningMethod: "HS512",
|
||||
MailFrom: mail.Address{Name: "happyDomain", Address: "happydomain@localhost"},
|
||||
MailSMTPPort: 587,
|
||||
StorageEngine: storage.StorageEngine("leveldb"),
|
||||
StorageEngine: "leveldb",
|
||||
}
|
||||
|
||||
opts.declareFlags()
|
||||
declareFlags(opts)
|
||||
|
||||
// Establish a list of possible configuration file locations
|
||||
configLocations := []string{
|
||||
|
@ -146,7 +72,7 @@ func ConsolidateConfig() (opts *Options, err error) {
|
|||
for _, filename := range configLocations {
|
||||
if _, e := os.Stat(filename); !os.IsNotExist(e) {
|
||||
log.Printf("Loading configuration from %s\n", filename)
|
||||
err = opts.parseFile(filename)
|
||||
err = parseFile(opts, filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -155,22 +81,22 @@ func ConsolidateConfig() (opts *Options, err error) {
|
|||
}
|
||||
|
||||
// Then, overwrite that by what is present in the environment
|
||||
err = opts.parseEnvironmentVariables()
|
||||
err = parseEnvironmentVariables(opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Finaly, command line takes precedence
|
||||
err = opts.parseCLI()
|
||||
err = parseCLI(opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Sanitize options
|
||||
if opts.baseURL != "/" {
|
||||
opts.baseURL = path.Clean(opts.baseURL)
|
||||
if opts.BasePath != "/" {
|
||||
opts.BasePath = path.Clean(opts.BasePath)
|
||||
} else {
|
||||
opts.baseURL = ""
|
||||
opts.BasePath = ""
|
||||
}
|
||||
|
||||
if opts.NoMail && opts.MailSMTPHost != "" {
|
||||
|
@ -178,26 +104,26 @@ func ConsolidateConfig() (opts *Options, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
if opts.ExternalURL.URL.Host == "" || opts.ExternalURL.URL.Scheme == "" {
|
||||
u, err2 := url.Parse("http://" + opts.ExternalURL.URL.String())
|
||||
if opts.ExternalURL.Host == "" || opts.ExternalURL.Scheme == "" {
|
||||
u, err2 := url.Parse("http://" + opts.ExternalURL.String())
|
||||
if err2 == nil {
|
||||
opts.ExternalURL.URL = u
|
||||
opts.ExternalURL = *u
|
||||
} else {
|
||||
err = fmt.Errorf("You defined an external URL without a scheme. The expected value is eg. http://localhost:8081")
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(opts.ExternalURL.URL.Path) > 1 {
|
||||
if opts.baseURL != "" && opts.baseURL != opts.ExternalURL.URL.Path {
|
||||
if len(opts.ExternalURL.Path) > 1 {
|
||||
if opts.BasePath != "" && opts.BasePath != opts.ExternalURL.Path {
|
||||
err = fmt.Errorf("You defined both baseurl and a path to externalurl that are different. Define only one of those.")
|
||||
return
|
||||
}
|
||||
|
||||
opts.baseURL = path.Clean(opts.ExternalURL.URL.Path)
|
||||
opts.BasePath = path.Clean(opts.ExternalURL.Path)
|
||||
}
|
||||
opts.ExternalURL.URL.Path = ""
|
||||
opts.ExternalURL.URL.Fragment = ""
|
||||
opts.ExternalURL.URL.RawQuery = ""
|
||||
opts.ExternalURL.Path = ""
|
||||
opts.ExternalURL.Fragment = ""
|
||||
opts.ExternalURL.RawQuery = ""
|
||||
|
||||
if len(opts.JWTSecretKey) == 0 {
|
||||
opts.JWTSecretKey = make([]byte, 32)
|
||||
|
@ -207,12 +133,17 @@ func ConsolidateConfig() (opts *Options, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
err = ExtendsConfigWithOIDC(opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// parseLine treats a config line and place the read value in the variable
|
||||
// declared to the corresponding flag.
|
||||
func (o *Options) parseLine(line string) (err error) {
|
||||
func parseLine(o *happydns.Options, line string) (err error) {
|
||||
fields := strings.SplitN(line, "=", 2)
|
||||
orig_key := strings.TrimSpace(fields[0])
|
||||
value := strings.TrimSpace(fields[1])
|
||||
|
|
|
@ -19,18 +19,20 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package config // import "git.happydns.org/happyDomain/config"
|
||||
package config // import "git.happydns.org/happyDomain/internal/config"
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func TestParseLine(t *testing.T) {
|
||||
cfg := Options{}
|
||||
cfg.declareFlags()
|
||||
cfg := &happydns.Options{}
|
||||
declareFlags(cfg)
|
||||
|
||||
err := cfg.parseLine("HAPPYDOMAIN_BIND=:8080")
|
||||
err := parseLine(cfg, "HAPPYDOMAIN_BIND=:8080")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("BIND=:8080") => %v`, err.Error())
|
||||
}
|
||||
|
@ -38,30 +40,30 @@ func TestParseLine(t *testing.T) {
|
|||
t.Fatalf(`parseLine("BIND=:8080") = %q, want ":8080"`, cfg.Bind)
|
||||
}
|
||||
|
||||
err = cfg.parseLine("BASEURL=/base")
|
||||
err = parseLine(cfg, "BASEURL=/base")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("BASEURL=/base") => %v`, err.Error())
|
||||
}
|
||||
if cfg.baseURL != "/base" {
|
||||
t.Fatalf(`parseLine("BASEURL=/base") = %q, want "/base"`, cfg.baseURL)
|
||||
if cfg.BasePath != "/base" {
|
||||
t.Fatalf(`parseLine("BASEURL=/base") = %q, want "/base"`, cfg.BasePath)
|
||||
}
|
||||
|
||||
cfg.parseLine("EXTERNALURL=https://happydomain.org")
|
||||
parseLine(cfg, "EXTERNALURL=https://happydomain.org")
|
||||
if cfg.ExternalURL.String() != "https://happydomain.org" {
|
||||
t.Fatalf(`parseLine("EXTERNAL_URL=https://happydomain.org") = %q, want "https://happydomain.org"`, cfg.ExternalURL)
|
||||
t.Fatalf(`parseLine("EXTERNAL_URL=https://happydomain.org") = %q, want "https://happydomain.org"`, cfg.ExternalURL.String())
|
||||
}
|
||||
|
||||
cfg.parseLine("DEFAULT-NS=42.42.42.42:5353")
|
||||
parseLine(cfg, "DEFAULT-NS=42.42.42.42:5353")
|
||||
if cfg.DefaultNameServer != "42.42.42.42:5353" {
|
||||
t.Fatalf(`parseLine("DEFAULT-NS=42.42.42.42:5353") = %q, want "42.42.42.42:5353"`, cfg.DefaultNameServer)
|
||||
}
|
||||
|
||||
cfg.parseLine("DEFAULT_NS=42.42.42.42:3535")
|
||||
parseLine(cfg, "DEFAULT_NS=42.42.42.42:3535")
|
||||
if cfg.DefaultNameServer != "42.42.42.42:3535" {
|
||||
t.Fatalf(`parseLine("DEFAULT_NS=42.42.42.42:3535") = %q, want "42.42.42.42:3535"`, cfg.DefaultNameServer)
|
||||
}
|
||||
|
||||
err = cfg.parseLine("NO_AUTH=true")
|
||||
err = parseLine(cfg, "NO_AUTH=true")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("NO_AUTH=true") => %v`, err.Error())
|
||||
}
|
||||
|
@ -73,8 +75,8 @@ func TestParseLine(t *testing.T) {
|
|||
func TestGetBaseURL(t *testing.T) {
|
||||
u, _ := url.Parse("http://localhost:8081")
|
||||
|
||||
cfg := Options{
|
||||
ExternalURL: URL{URL: u},
|
||||
cfg := &happydns.Options{
|
||||
ExternalURL: *u,
|
||||
}
|
||||
|
||||
builded_url := cfg.GetBaseURL()
|
||||
|
@ -82,7 +84,7 @@ func TestGetBaseURL(t *testing.T) {
|
|||
t.Fatalf(`GetBaseURL() = %q, want "http://localhost:8081"`, builded_url)
|
||||
}
|
||||
|
||||
cfg.baseURL = "/base"
|
||||
cfg.BasePath = "/base"
|
||||
|
||||
builded_url = cfg.GetBaseURL()
|
||||
if builded_url != "http://localhost:8081/base" {
|
||||
|
|
|
@ -27,10 +27,12 @@ import (
|
|||
"net/url"
|
||||
)
|
||||
|
||||
type JWTSecretKey []byte
|
||||
type JWTSecretKey struct {
|
||||
Secret *[]byte
|
||||
}
|
||||
|
||||
func (i *JWTSecretKey) String() string {
|
||||
return base64.StdEncoding.EncodeToString(*i)
|
||||
return base64.StdEncoding.EncodeToString(*i.Secret)
|
||||
}
|
||||
|
||||
func (i *JWTSecretKey) Set(value string) error {
|
||||
|
@ -39,7 +41,7 @@ func (i *JWTSecretKey) Set(value string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
*i = z
|
||||
*i.Secret = z
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -83,6 +85,6 @@ func (i *URL) Set(value string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
i.URL = u
|
||||
*i.URL = *u
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,14 +25,16 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
// parseEnvironmentVariables analyzes all the environment variables to find
|
||||
// each one starting by HAPPYDOMAIN_
|
||||
func (o *Options) parseEnvironmentVariables() (err error) {
|
||||
func parseEnvironmentVariables(o *happydns.Options) (err error) {
|
||||
for _, line := range os.Environ() {
|
||||
if strings.HasPrefix(line, "HAPPYDOMAIN_") || strings.HasPrefix(line, "HAPPYDNS_") {
|
||||
err := o.parseLine(line)
|
||||
err := parseLine(o, line)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error in environment (%q): %w", line, err)
|
||||
}
|
||||
|
|
|
@ -26,11 +26,13 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
// parseFile opens the file at the given filename path, then treat each line
|
||||
// not starting with '#' as a configuration statement.
|
||||
func (o *Options) parseFile(filename string) error {
|
||||
func parseFile(o *happydns.Options, filename string) error {
|
||||
fp, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -43,7 +45,7 @@ func (o *Options) parseFile(filename string) error {
|
|||
n += 1
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if len(line) > 0 && !strings.HasPrefix(line, "#") && strings.Index(line, "=") > 0 {
|
||||
err := o.parseLine(line)
|
||||
err := parseLine(o, line)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v:%d: error in configuration: %w", filename, n, err)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
package config
|
||||
|
||||
func (o *Options) GetOIDCProviderURL() string {
|
||||
return ""
|
||||
import (
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func ExtendsConfigWithOIDC(o *happydns.Options) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -24,50 +24,32 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"golang.org/x/oauth2"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
var (
|
||||
OIDCClientID string
|
||||
oidcClientID string
|
||||
oidcClientSecret string
|
||||
OIDCProviderURL string
|
||||
oidcProviderURL url.URL
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&OIDCClientID, "oidc-client-id", OIDCClientID, "ClientID for OIDC")
|
||||
flag.StringVar(&oidcClientID, "oidc-client-id", oidcClientID, "ClientID for OIDC")
|
||||
flag.StringVar(&oidcClientSecret, "oidc-client-secret", oidcClientSecret, "Secret for OIDC")
|
||||
flag.StringVar(&OIDCProviderURL, "oidc-provider-url", OIDCProviderURL, "Base URL of the OpenId Connect service")
|
||||
flag.Var(&URL{&oidcProviderURL}, "oidc-provider-url", "Base URL of the OpenId Connect service")
|
||||
}
|
||||
|
||||
func (o *Options) GetAuthURL() *url.URL {
|
||||
redirecturl := *o.ExternalURL.URL
|
||||
redirecturl.Path = path.Join(redirecturl.Path, o.baseURL, "auth", "callback")
|
||||
return &redirecturl
|
||||
}
|
||||
|
||||
func (o *Options) GetOIDCProvider(ctx context.Context) (*oidc.Provider, error) {
|
||||
return oidc.NewProvider(ctx, strings.TrimSuffix(OIDCProviderURL, "/.well-known/openid-configuration"))
|
||||
}
|
||||
|
||||
func (o *Options) GetOIDCProviderURL() string {
|
||||
return OIDCProviderURL
|
||||
}
|
||||
|
||||
func (o *Options) GetOAuth2Config(provider *oidc.Provider) *oauth2.Config {
|
||||
oauth2Config := oauth2.Config{
|
||||
ClientID: OIDCClientID,
|
||||
ClientSecret: oidcClientSecret,
|
||||
RedirectURL: o.GetAuthURL().String(),
|
||||
Endpoint: provider.Endpoint(),
|
||||
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
|
||||
func ExtendsConfigWithOIDC(o *happydns.Options) error {
|
||||
if oidcProviderURL.String() != "" {
|
||||
o.OIDCClients = append(o.OIDCClients, happydns.OIDCSettings{
|
||||
ClientID: oidcClientID,
|
||||
ClientSecret: oidcClientSecret,
|
||||
ProviderURL: oidcProviderURL,
|
||||
})
|
||||
}
|
||||
|
||||
return &oauth2Config
|
||||
return nil
|
||||
}
|
||||
|
|
82
internal/config/oidc_test.go
Normal file
82
internal/config/oidc_test.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nooidc
|
||||
|
||||
package config // import "git.happydns.org/happyDomain/internal/config"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func TestOIDCConfig(t *testing.T) {
|
||||
cfg := &happydns.Options{}
|
||||
|
||||
err := parseLine(cfg, "HAPPYDOMAIN_OIDC_CLIENT_ID=test-oidc-1")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_CLIENT_ID=test-oidc-1") => %v`, err.Error())
|
||||
}
|
||||
if oidcClientID != "test-oidc-1" {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_CLIENT_ID=test-oidc-1") = %q, want "test-oidc-1"`, oidcClientID)
|
||||
}
|
||||
|
||||
err = parseLine(cfg, "HAPPYDOMAIN_OIDC_CLIENT_SECRET=s3cret$")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_CLIENT_SECRET=s3cret$") => %v`, err.Error())
|
||||
}
|
||||
if oidcClientSecret != "s3cret$" {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_CLIENT_SECRET=s3cret$") = %q, want "s3cret$"`, oidcClientSecret)
|
||||
}
|
||||
|
||||
if oidcProviderURL.String() != "" {
|
||||
t.Fatalf(`before parseLine("HAPPYDOMAIN_OIDC_PROVIDER_URL") = %q, want ""`, oidcProviderURL.String())
|
||||
}
|
||||
|
||||
err = parseLine(cfg, "HAPPYDOMAIN_OIDC_PROVIDER_URL=https://localhost:12345/secret")
|
||||
if err != nil {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_PROVIDER_URL=https://localhost:12345/secret") => %v`, err.Error())
|
||||
}
|
||||
if oidcProviderURL.String() != "https://localhost:12345/secret" {
|
||||
t.Fatalf(`parseLine("HAPPYDOMAIN_OIDC_PROVIDER_URL=https://localhost:12345/secret") = %q, want "https://localhost:12345/secret"`, cfg.Bind)
|
||||
}
|
||||
|
||||
// Test extended config
|
||||
err = ExtendsConfigWithOIDC(cfg)
|
||||
if err != nil {
|
||||
t.Fatalf(`ExtendsConfigWithOIDC(cfg) => %v`, err.Error())
|
||||
}
|
||||
|
||||
if len(cfg.OIDCClients) != 1 {
|
||||
t.Fatalf(`len(cfg.OIDCClients) == %d, should be 1`, len(cfg.OIDCClients))
|
||||
}
|
||||
|
||||
if cfg.OIDCClients[0].ClientID != "test-oidc-1" {
|
||||
t.Fatalf(`cfg.OIDCClients[0].ClientID == %q, should be test-oidc-1`, cfg.OIDCClients[0].ClientID)
|
||||
}
|
||||
if cfg.OIDCClients[0].ClientSecret != "s3cret$" {
|
||||
t.Fatalf(`cfg.OIDCClients[0].ClientSecret == %q, should be test-oidc-1`, cfg.OIDCClients[0].ClientSecret)
|
||||
}
|
||||
if cfg.OIDCClients[0].ProviderURL.String() != "https://localhost:12345/secret" {
|
||||
t.Fatalf(`cfg.OIDCClients[0].ProviderURL == %q, should be https://localhost:12345/secret`, cfg.OIDCClients[0].ProviderURL.String())
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -19,7 +19,7 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"github.com/miekg/dns"
|
|
@ -19,7 +19,7 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
|
@ -19,7 +19,7 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package utils
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"strings"
|
|
@ -27,7 +27,7 @@ import (
|
|||
"net/mail"
|
||||
"text/template"
|
||||
|
||||
"git.happydns.org/happyDomain/ui"
|
||||
"git.happydns.org/happyDomain/web"
|
||||
|
||||
gomail "github.com/go-mail/mail"
|
||||
"github.com/yuin/goldmark"
|
||||
|
@ -95,7 +95,7 @@ func (r *Mailer) SendMail(to *mail.Address, subject, content string) (err error)
|
|||
return
|
||||
}
|
||||
|
||||
if data, err := ui.GetEmbedFS().Open("dist/img/happydomain.png"); err == nil {
|
||||
if data, err := web.GetEmbedFS().Open("dist/img/happydomain.png"); err == nil {
|
||||
m.EmbedReader("happydomain.png", data)
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
"net/url"
|
||||
"path/filepath"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/utils"
|
||||
"git.happydns.org/happyDomain/internal/helpers"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -49,8 +49,8 @@ type ListmonkSubscriber struct {
|
|||
}
|
||||
|
||||
func (ns *ListmonkNewsletterSubscription) SubscribeToNewsletter(u happydns.UserInfo) error {
|
||||
if ns.ListmonkId != 0 {
|
||||
log.Println("SubscribeToNewsletter: not subscribing user as newsletter server is not defined.")
|
||||
if ns.ListmonkId == 0 {
|
||||
log.Println("SubscribeToNewsletter: not subscribing user as newsletter list id is not defined.")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ func (ns *ListmonkNewsletterSubscription) SubscribeToNewsletter(u happydns.UserI
|
|||
|
||||
jsonForm := &ListmonkSubscriber{
|
||||
Email: u.GetEmail(),
|
||||
Name: utils.GenUsername(u.GetEmail()),
|
||||
Name: helpers.GenUsername(u.GetEmail()),
|
||||
Status: "enabled",
|
||||
Lists: []int{ns.ListmonkId},
|
||||
PreconfirmSubscriptions: true,
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
package session // import "git.happydns.org/happyDomain/internal/session"
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
@ -33,8 +32,7 @@ import (
|
|||
"github.com/gorilla/sessions"
|
||||
"github.com/mileusna/useragent"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/config"
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
sessionUC "git.happydns.org/happyDomain/internal/usecase/session"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
|
@ -44,18 +42,18 @@ const COOKIE_NAME = "happydomain_session"
|
|||
type SessionStore struct {
|
||||
Codecs []securecookie.Codec
|
||||
options *sessions.Options
|
||||
storage storage.Storage
|
||||
storage sessionUC.SessionStorage
|
||||
}
|
||||
|
||||
func NewSessionStore(opts *config.Options, storage storage.Storage, keyPairs ...[]byte) *SessionStore {
|
||||
func NewSessionStore(opts *happydns.Options, storage sessionUC.SessionStorage, keyPairs ...[]byte) *SessionStore {
|
||||
store := &SessionStore{
|
||||
Codecs: securecookie.CodecsFromPairs(keyPairs...),
|
||||
options: &sessions.Options{
|
||||
Path: opts.GetBasePath() + "/",
|
||||
Path: opts.BasePath + "/",
|
||||
MaxAge: 86400 * 30,
|
||||
Secure: opts.DevProxy == "" && opts.ExternalURL.URL.Scheme != "http",
|
||||
Secure: opts.DevProxy == "" && opts.ExternalURL.Scheme != "http",
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
},
|
||||
storage: storage,
|
||||
}
|
||||
|
@ -107,7 +105,7 @@ func (s *SessionStore) Save(r *http.Request, w http.ResponseWriter, session *ses
|
|||
s.storage.DeleteSession(session.ID)
|
||||
} else {
|
||||
if session.ID == "" {
|
||||
session.ID = NewSessionId()
|
||||
session.ID = sessionUC.NewSessionId()
|
||||
}
|
||||
encrypted, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...)
|
||||
if err != nil {
|
||||
|
@ -173,13 +171,28 @@ func (s *SessionStore) load(session *sessions.Session) error {
|
|||
|
||||
// save writes encoded session.Values to a database record.
|
||||
func (s *SessionStore) save(session *sessions.Session, ua string) error {
|
||||
encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...)
|
||||
if err != nil {
|
||||
return err
|
||||
var iduser happydns.Identifier
|
||||
if iu, ok := session.Values["iduser"].(happydns.Identifier); ok {
|
||||
iduser = iu
|
||||
} else if iu, ok := session.Values["iduser"].([]byte); ok {
|
||||
iduser = happydns.Identifier(iu)
|
||||
}
|
||||
delete(session.Values, "iduser")
|
||||
|
||||
var description string
|
||||
if descr, ok := session.Values["description"].(string); ok {
|
||||
description = descr
|
||||
} else {
|
||||
browser := useragent.Parse(ua)
|
||||
description = fmt.Sprintf("%s on %s", browser.Name, browser.OS)
|
||||
session.Values["description"] = description
|
||||
}
|
||||
delete(session.Values, "description")
|
||||
|
||||
crOn := session.Values["created_on"]
|
||||
delete(session.Values, "created_on")
|
||||
exOn := session.Values["expires_on"]
|
||||
delete(session.Values, "expires_on")
|
||||
|
||||
var expiresOn time.Time
|
||||
|
||||
|
@ -197,20 +210,9 @@ func (s *SessionStore) save(session *sessions.Session, ua string) error {
|
|||
}
|
||||
}
|
||||
|
||||
var iduser happydns.Identifier
|
||||
if iu, ok := session.Values["iduser"].(happydns.Identifier); ok {
|
||||
iduser = iu
|
||||
} else if iu, ok := session.Values["iduser"].([]byte); ok {
|
||||
iduser = happydns.Identifier(iu)
|
||||
}
|
||||
|
||||
var description string
|
||||
if descr, ok := session.Values["description"].(string); ok {
|
||||
description = descr
|
||||
} else {
|
||||
browser := useragent.Parse(ua)
|
||||
description = fmt.Sprintf("%s on %s", browser.Name, browser.OS)
|
||||
session.Values["description"] = description
|
||||
encoded, err := securecookie.EncodeMulti(session.Name(), session.Values, s.Codecs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mysession := &happydns.Session{
|
||||
|
@ -225,7 +227,3 @@ func (s *SessionStore) save(session *sessions.Session, ua string) error {
|
|||
|
||||
return s.storage.UpdateSession(mysession)
|
||||
}
|
||||
|
||||
func NewSessionId() string {
|
||||
return strings.TrimRight(base32.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(64)), "=")
|
||||
}
|
||||
|
|
129
internal/storage/inmemory/auth_user.go
Normal file
129
internal/storage/inmemory/auth_user.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package inmemory
|
||||
|
||||
import (
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
func (s *InMemoryStorage) ListAllAuthUsers() (happydns.Iterator[happydns.UserAuth], error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
return NewInMemoryIterator[happydns.UserAuth](&s.authUsers), nil
|
||||
}
|
||||
|
||||
// ListAuthUsers retrieves the list of known Users.
|
||||
func (s *InMemoryStorage) ListAuthUsers() (happydns.UserAuths, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
var users happydns.UserAuths
|
||||
for _, user := range s.authUsers {
|
||||
users = append(users, user)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// GetAuthUser retrieves the User with the given identifier.
|
||||
func (s *InMemoryStorage) GetAuthUser(id happydns.Identifier) (*happydns.UserAuth, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
user, exists := s.authUsers[id.String()]
|
||||
if !exists {
|
||||
return nil, happydns.ErrAuthUserNotFound
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// GetAuthUserByEmail retrieves the User with the given email address.
|
||||
func (s *InMemoryStorage) GetAuthUserByEmail(email string) (*happydns.UserAuth, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
userid, exists := s.authUsersByEmail[email]
|
||||
if !exists {
|
||||
return nil, happydns.ErrAuthUserNotFound
|
||||
}
|
||||
|
||||
user, exists := s.authUsers[userid.String()]
|
||||
if !exists {
|
||||
return nil, happydns.ErrAuthUserNotFound
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// AuthUserExists checks if the given email address is already associated to an User.
|
||||
func (s *InMemoryStorage) AuthUserExists(email string) (bool, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
_, exists := s.authUsersByEmail[email]
|
||||
return exists, nil
|
||||
}
|
||||
|
||||
// CreateAuthUser creates a record in the database for the given User.
|
||||
func (s *InMemoryStorage) CreateAuthUser(user *happydns.UserAuth) (err error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
user.Id, err = happydns.NewRandomIdentifier()
|
||||
s.authUsers[user.Id.String()] = user
|
||||
s.authUsersByEmail[user.Email] = user.Id
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateAuthUser updates the fields of the given User.
|
||||
func (s *InMemoryStorage) UpdateAuthUser(user *happydns.UserAuth) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.authUsers[user.Id.String()] = user
|
||||
s.authUsersByEmail[user.Email] = user.Id
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAuthUser removes the given User from the database.
|
||||
func (s *InMemoryStorage) DeleteAuthUser(user *happydns.UserAuth) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
delete(s.authUsers, user.Id.String())
|
||||
delete(s.authUsersByEmail, user.Email)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearAuthUsers deletes all AuthUsers present in the database.
|
||||
func (s *InMemoryStorage) ClearAuthUsers() error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.authUsers = make(map[string]*happydns.UserAuth)
|
||||
s.authUsersByEmail = make(map[string]happydns.Identifier)
|
||||
|
||||
return nil
|
||||
}
|
34
internal/storage/inmemory/config.go
Normal file
34
internal/storage/inmemory/config.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package inmemory
|
||||
|
||||
import (
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
)
|
||||
|
||||
func init() {
|
||||
storage.StorageEngines["inmemory"] = Instantiate
|
||||
}
|
||||
|
||||
func Instantiate() (storage.Storage, error) {
|
||||
return NewInMemoryStorage()
|
||||
}
|
87
internal/storage/inmemory/database.go
Normal file
87
internal/storage/inmemory/database.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2025 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
//
|
||||
// This program is offered under a commercial and under the AGPL license.
|
||||
// For commercial licensing, contact us at <contact@happydomain.org>.
|
||||
//
|
||||
// For AGPL licensing:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package inmemory
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.happydns.org/happyDomain/model"
|
||||
)
|
||||
|
||||
// InMemoryStorage implements the Storage interface using in-memory data structures.
|
||||
type InMemoryStorage struct {
|
||||
mu sync.Mutex
|
||||
authUsers map[string]*happydns.UserAuth
|
||||
authUsersByEmail map[string]happydns.Identifier
|
||||
domains map[string]*happydns.Domain
|
||||
domainLogs map[string]*happydns.DomainLogWithDomainId
|
||||
domainLogsByDomains map[string][]*happydns.Identifier
|
||||
providers map[string]*happydns.ProviderMessage
|
||||
sessions map[string]*happydns.Session
|
||||
users map[string]*happydns.User
|
||||
usersByEmail map[string]*happydns.User
|
||||
zones map[string]*happydns.ZoneMessage
|
||||
lastInsightsRun *time.Time
|
||||
lastInsightsID happydns.Identifier
|
||||
}
|
||||
|
||||
// NewInMemoryStorage creates a new instance of InMemoryStorage.
|
||||
func NewInMemoryStorage() (*InMemoryStorage, error) {
|
||||
return &InMemoryStorage{
|
||||
authUsers: make(map[string]*happydns.UserAuth),
|
||||
authUsersByEmail: make(map[string]happydns.Identifier),
|
||||
domains: make(map[string]*happydns.Domain),
|
||||
domainLogs: make(map[string]*happydns.DomainLogWithDomainId),
|
||||
domainLogsByDomains: make(map[string][]*happydns.Identifier),
|
||||
providers: make(map[string]*happydns.ProviderMessage),
|
||||
sessions: make(map[string]*happydns.Session),
|
||||
users: make(map[string]*happydns.User),
|
||||
usersByEmail: make(map[string]*happydns.User),
|
||||
zones: make(map[string]*happydns.ZoneMessage),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SchemaVersion returns the version of the migration currently in use.
|
||||
func (s *InMemoryStorage) SchemaVersion() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// DoMigration is the first function called.
|
||||
func (s *InMemoryStorage) MigrateSchema() error {
|
||||
log.Println("YOU ARE USING THE inmemory STORAGE: DATA WILL BE LOST ON HAPPYDOMAIN STOP.")
|
||||
// No migration needed for in-memory storage.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tidy should optimize the database, looking for orphan records, ...
|
||||
func (s *InMemoryStorage) Tidy() error {
|
||||
// No tidy needed for in-memory storage.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close shutdown the connection with the database and releases all structure.
|
||||
func (s *InMemoryStorage) Close() error {
|
||||
// No connection to close for in-memory storage.
|
||||
return nil
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue