Experiment with Authentication and Websockets
Some checks failed
build-docker-imge / Build the docker container (push) Failing after 2m24s
Some checks failed
build-docker-imge / Build the docker container (push) Failing after 2m24s
This commit is contained in:
parent
768c178218
commit
1e41dd833f
30
.gitea/workflows/release-tag.yml
Normal file
30
.gitea/workflows/release-tag.yml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
name: build-docker-imge
|
||||||
|
on:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build the docker container
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Print env"
|
||||||
|
run: echo WORKSPACE
|
||||||
|
- name: "Git clone"
|
||||||
|
run: git clone ${{ gitea.server_url }}/${{ gitea.repository }}.git .
|
||||||
|
- name: "LS"
|
||||||
|
run: ls -lisa
|
||||||
|
- name: "LS ECHO"
|
||||||
|
run: echo "$(ls)" "${{ gitea.repository }}" "${{ gitea.ref_name }}" "${{ gitea.sha }}"
|
||||||
|
- name: "Git checkout"
|
||||||
|
run: git checkout "${{ gitea.sha }}"
|
||||||
|
- uses: aevea/action-kaniko@master
|
||||||
|
name: Run Kaniko to build our docker container.
|
||||||
|
with:
|
||||||
|
image: kocoded/gitea-workspaces/szuntis-backend-main
|
||||||
|
tag: ${{ gitea.workflow_sha }}
|
||||||
|
tag_with_latest: true
|
||||||
|
registry: git.kocoder.xyz
|
||||||
|
username: ${{ secrets.CI_RUNNER_USER }}
|
||||||
|
password: ${{ secrets.CI_RUNNER_TOKEN }}
|
||||||
|
build_file: DOCKERFILE
|
27
DOCKERFILE
Normal file
27
DOCKERFILE
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
FROM golang:1.21.0
|
||||||
|
|
||||||
|
# Set destination for COPY
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Download Go modules
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
# Copy the source code. Note the slash at the end, as explained in
|
||||||
|
# https://docs.docker.com/engine/reference/builder/#copy
|
||||||
|
COPY *.go ./
|
||||||
|
|
||||||
|
# Build
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -o /szuntis-backend
|
||||||
|
|
||||||
|
# Optional:
|
||||||
|
# To bind to a TCP port, runtime parameters must be supplied to the docker command.
|
||||||
|
# But we can document in the Dockerfile what ports
|
||||||
|
# the application is going to listen on by default.
|
||||||
|
# https://docs.docker.com/engine/reference/builder/#expose
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Run
|
||||||
|
CMD ["/szuntis-backend"]
|
78
auth/memory.go
Normal file
78
auth/memory.go
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/repository"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type authRepository struct {
|
||||||
|
users map[string]repository.User //map[LoginName]User
|
||||||
|
sessions map[uuid.UUID]string //map[sessionToken]email
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMemeoryAuthRepository() repository.AuthRepository {
|
||||||
|
return &authRepository{
|
||||||
|
users: map[string]repository.User{},
|
||||||
|
sessions: map[uuid.UUID]string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authRepository) GetUserByToken(ctx context.Context, userId uuid.UUID) (repository.User, error) {
|
||||||
|
ln, ok := a.sessions[userId]
|
||||||
|
if !ok {
|
||||||
|
return repository.User{}, errors.New("you have to be logged in to do that")
|
||||||
|
}
|
||||||
|
|
||||||
|
u, ok := a.users[ln]
|
||||||
|
if !ok {
|
||||||
|
return repository.User{}, errors.New("you have to be logged in to do that")
|
||||||
|
}
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authRepository) Login(ctx context.Context, loginParams *repository.LoginParams) (uuid.UUID, error) {
|
||||||
|
u, ok := a.users[loginParams.LoginName]
|
||||||
|
if !ok {
|
||||||
|
return uuid.Nil, errors.New("couldn't log user in")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bcrypt.CompareHashAndPassword(u.Password, []byte(loginParams.Password)); err != nil {
|
||||||
|
return uuid.Nil, errors.New("couldn't log user in")
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionToken, err := uuid.NewUUID()
|
||||||
|
if err != nil {
|
||||||
|
return uuid.Nil, errors.New("couldn't log user in")
|
||||||
|
}
|
||||||
|
a.sessions[sessionToken] = loginParams.LoginName
|
||||||
|
|
||||||
|
return sessionToken, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *authRepository) Register(ctx context.Context, registerParams *repository.RegisterParams) (bool, error) {
|
||||||
|
if _, ok := a.users[registerParams.LoginName]; ok {
|
||||||
|
return false, errors.New("couldn't register user")
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := bcrypt.GenerateFromPassword([]byte(registerParams.Password), 7)
|
||||||
|
if err != nil {
|
||||||
|
return false, errors.New("couldn't register user")
|
||||||
|
}
|
||||||
|
|
||||||
|
u := repository.User{
|
||||||
|
Username: registerParams.Username,
|
||||||
|
FirstName: registerParams.FirstName,
|
||||||
|
LastName: registerParams.LastName,
|
||||||
|
LoginName: registerParams.LoginName,
|
||||||
|
EmailAddress: registerParams.EmailAddress,
|
||||||
|
Password: res,
|
||||||
|
}
|
||||||
|
|
||||||
|
a.users[registerParams.LoginName] = u
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
59
authentication/types.go
Normal file
59
authentication/types.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package authentication
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserAccount struct {
|
||||||
|
gorm.Model
|
||||||
|
Username string
|
||||||
|
FirstName string
|
||||||
|
LastName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type HashingAlgorithm struct {
|
||||||
|
gorm.Model
|
||||||
|
AlgoritmName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmailValidationStatus struct {
|
||||||
|
gorm.Model
|
||||||
|
StatusDescription string
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserLoginData struct {
|
||||||
|
gorm.Model
|
||||||
|
LoginName string
|
||||||
|
PasswordHash []byte
|
||||||
|
PassswordSalt []byte
|
||||||
|
EmailAddress string
|
||||||
|
ConfirmationToken string
|
||||||
|
TokenGenerationTime time.Time
|
||||||
|
PasswordRecoveryToken string
|
||||||
|
RecoveryTokenTime time.Time
|
||||||
|
|
||||||
|
EmailValidationStatusId int
|
||||||
|
EmailValidationStatus EmailValidationStatus
|
||||||
|
|
||||||
|
UserAccountID int
|
||||||
|
UserAccount UserAccount
|
||||||
|
|
||||||
|
HashingAlgorithmID int
|
||||||
|
HashingAlgorithm HashingAlgorithm
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserLoginDataExternal struct {
|
||||||
|
gorm.Model
|
||||||
|
ExternalProviderToken string
|
||||||
|
|
||||||
|
ExternalProviderID int
|
||||||
|
ExternalProvider ExternalProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalProvider struct {
|
||||||
|
gorm.Model
|
||||||
|
ProviderName string
|
||||||
|
WSEndPoint string
|
||||||
|
}
|
33
go.mod
Normal file
33
go.mod
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
module git.kocoder.xyz/kocoded/szuntis-backend
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
|
github.com/fasthttp/websocket v1.5.8 // indirect
|
||||||
|
github.com/gofiber/contrib/websocket v1.3.2 // indirect
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.5 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5 // indirect
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.7 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.52.0 // indirect
|
||||||
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
golang.org/x/crypto v0.26.0 // indirect
|
||||||
|
golang.org/x/net v0.23.0 // indirect
|
||||||
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
|
golang.org/x/text v0.17.0 // indirect
|
||||||
|
gorm.io/driver/postgres v1.5.9 // indirect
|
||||||
|
gorm.io/gorm v1.25.11 // indirect
|
||||||
|
)
|
81
go.sum
Normal file
81
go.sum
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fasthttp/websocket v1.5.8 h1:k5DpirKkftIF/w1R8ZzjSgARJrs54Je9YJK37DL/Ah8=
|
||||||
|
github.com/fasthttp/websocket v1.5.8/go.mod h1:d08g8WaT6nnyvg9uMm8K9zMYyDjfKyj3170AtPRuVU0=
|
||||||
|
github.com/gofiber/contrib/websocket v1.3.2 h1:AUq5PYeKwK50s0nQrnluuINYeep1c4nRCJ0NWsV3cvg=
|
||||||
|
github.com/gofiber/contrib/websocket v1.3.2/go.mod h1:07u6QGMsvX+sx7iGNCl5xhzuUVArWwLQ3tBIH24i+S8=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||||
|
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||||
|
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511 h1:KanIMPX0QdEdB4R3CiimCAbxFrhB3j7h0/OvpYGVQa8=
|
||||||
|
github.com/savsgio/gotils v0.0.0-20240303185622-093b76447511/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||||
|
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||||
|
github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
|
||||||
|
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
|
||||||
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
|
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||||
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||||
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||||
|
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||||
|
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8=
|
||||||
|
gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
|
||||||
|
gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
|
||||||
|
gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
28
main.go
Normal file
28
main.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/auth"
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/middleware"
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/router"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// dsn := "postgresql://app1:p5ohxMubZHhzsvSQevlFfw@cockroach-db-1-11072.7tc.aws-eu-central-1.cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full"
|
||||||
|
// db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal("failed to connect database", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
ar := auth.NewMemeoryAuthRepository()
|
||||||
|
app := fiber.New()
|
||||||
|
|
||||||
|
api := app.Group("/api")
|
||||||
|
router.NewAuthRouter(ar, middleware.NewAuthMiddleware(ar), api.Group("auth"))
|
||||||
|
router.NewWebSocketRouter(middleware.NewWsMiddleware(), api.Group("web"))
|
||||||
|
api.Use(middleware.NewWsMiddleware().IsWebscoketUpgrade)
|
||||||
|
|
||||||
|
log.Fatal(app.Listen(":3000"))
|
||||||
|
}
|
41
middleware/auth.go
Normal file
41
middleware/auth.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/repository"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthMiddleware struct {
|
||||||
|
ar repository.AuthRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuthMiddleware(ar repository.AuthRepository) AuthMiddleware {
|
||||||
|
return AuthMiddleware{
|
||||||
|
ar: ar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am AuthMiddleware) IsAuthenticated(ctx *fiber.Ctx) error {
|
||||||
|
val := ctx.Cookies("session-token")
|
||||||
|
if val == "" {
|
||||||
|
fmt.Println(1)
|
||||||
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
token, err := uuid.Parse(val)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(2)
|
||||||
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := am.ar.GetUserByToken(ctx.Context(), token)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(3)
|
||||||
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
fmt.Println(4)
|
||||||
|
ctx.Locals("user", u)
|
||||||
|
return ctx.Next()
|
||||||
|
}
|
20
middleware/ws.go
Normal file
20
middleware/ws.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gofiber/contrib/websocket"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WsMiddleware struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWsMiddleware() WsMiddleware {
|
||||||
|
return WsMiddleware{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm WsMiddleware) IsWebscoketUpgrade(ctx *fiber.Ctx) error {
|
||||||
|
if websocket.IsWebSocketUpgrade(ctx) {
|
||||||
|
return ctx.Next()
|
||||||
|
}
|
||||||
|
return ctx.SendStatus(fiber.StatusUpgradeRequired)
|
||||||
|
}
|
36
repository/auth.go
Normal file
36
repository/auth.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoginParams struct {
|
||||||
|
LoginName string `json:"loginname"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterParams struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
FirstName string `json:"firstname"`
|
||||||
|
LastName string `json:"lastname"`
|
||||||
|
LoginName string `json:"loginname"`
|
||||||
|
EmailAddress string `json:"emailaddress"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Username string `json:"username"`
|
||||||
|
FirstName string `json:"firstname"`
|
||||||
|
LastName string `json:"lastname"`
|
||||||
|
LoginName string `json:"loginname"`
|
||||||
|
EmailAddress string `json:"email"`
|
||||||
|
Password []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthRepository interface {
|
||||||
|
GetUserByToken(ctx context.Context, userId uuid.UUID) (User, error)
|
||||||
|
Login(ctx context.Context, loginParams *LoginParams) (uuid.UUID, error)
|
||||||
|
Register(ctx context.Context, registerParams *RegisterParams) (bool, error)
|
||||||
|
}
|
70
router/auth.go
Normal file
70
router/auth.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/middleware"
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/repository"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthRouter struct {
|
||||||
|
authRepo repository.AuthRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuthRouter(authRepo repository.AuthRepository, authMiddleware middleware.AuthMiddleware, auth fiber.Router) error {
|
||||||
|
router := &AuthRouter{authRepo: authRepo}
|
||||||
|
auth.Post("/login", router.HandleLogin)
|
||||||
|
auth.Post("/register", router.HandleRegister)
|
||||||
|
auth.Get("/username", authMiddleware.IsAuthenticated, router.GetName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ar AuthRouter) GetName(ctx *fiber.Ctx) error {
|
||||||
|
|
||||||
|
user, ok := ctx.Locals("user").(repository.User)
|
||||||
|
if !ok {
|
||||||
|
return ctx.SendStatus(fiber.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.SendString(user.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ar AuthRouter) HandleLogin(ctx *fiber.Ctx) error {
|
||||||
|
params := repository.LoginParams{}
|
||||||
|
if err := ctx.BodyParser(¶ms); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := ar.authRepo.Login(ctx.Context(), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie := &fiber.Cookie{
|
||||||
|
Name: "session-token",
|
||||||
|
Value: token.String(),
|
||||||
|
MaxAge: 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Cookie(cookie)
|
||||||
|
return ctx.SendString("Success!!!!!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ar AuthRouter) HandleRegister(ctx *fiber.Ctx) error {
|
||||||
|
params := repository.RegisterParams{}
|
||||||
|
if err := ctx.BodyParser(¶ms); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := ar.authRepo.Register(ctx.Context(), ¶ms)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return ctx.SendString("User registered successfully, please check your inbox & proceed to login.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New("")
|
||||||
|
}
|
100
router/home.html
Normal file
100
router/home.html
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<!-- See https://github.com/gorilla/websocket/blob/master/examples/chat/home.html -->
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Chat Example</title>
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.onload = function () {
|
||||||
|
var conn;
|
||||||
|
var msg = document.getElementById("msg");
|
||||||
|
var log = document.getElementById("log");
|
||||||
|
|
||||||
|
function appendLog(item) {
|
||||||
|
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
|
||||||
|
log.appendChild(item);
|
||||||
|
if (doScroll) {
|
||||||
|
log.scrollTop = log.scrollHeight - log.clientHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("form").onsubmit = function () {
|
||||||
|
if (!conn) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!msg.value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
conn.send(msg.value);
|
||||||
|
msg.value = "";
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (window["WebSocket"]) {
|
||||||
|
conn = new WebSocket("ws://" + document.location.host + "/api/web/ws");
|
||||||
|
conn.onclose = function (evt) {
|
||||||
|
var item = document.createElement("div");
|
||||||
|
item.innerHTML = "<b>Connection closed.</b>";
|
||||||
|
appendLog(item);
|
||||||
|
};
|
||||||
|
conn.onmessage = function (evt) {
|
||||||
|
var messages = evt.data.split('\n');
|
||||||
|
for (var i = 0; i < messages.length; i++) {
|
||||||
|
var item = document.createElement("div");
|
||||||
|
item.innerText = messages[i];
|
||||||
|
appendLog(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
var item = document.createElement("div");
|
||||||
|
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
|
||||||
|
appendLog(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style type="text/css">
|
||||||
|
html {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#log {
|
||||||
|
background: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5em 0.5em 0.5em 0.5em;
|
||||||
|
position: absolute;
|
||||||
|
top: 0.5em;
|
||||||
|
left: 0.5em;
|
||||||
|
right: 0.5em;
|
||||||
|
bottom: 3em;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form {
|
||||||
|
padding: 0 0.5em 0 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1em;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="log"></div>
|
||||||
|
<form id="form">
|
||||||
|
<input type="submit" value="Send" />
|
||||||
|
<input type="text" id="msg" size="64" autofocus autocomplete="off" />
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
router/home.html.fiber.gz
Normal file
BIN
router/home.html.fiber.gz
Normal file
Binary file not shown.
83
router/websocket.go
Normal file
83
router/websocket.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.kocoder.xyz/kocoded/szuntis-backend/middleware"
|
||||||
|
"github.com/gofiber/contrib/websocket"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WebSocketRouter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebSocketRouter(authMiddleware middleware.WsMiddleware, ws fiber.Router) error {
|
||||||
|
router := &WebSocketRouter{}
|
||||||
|
go RunHub()
|
||||||
|
ws.Get("/", func(c *fiber.Ctx) error {
|
||||||
|
return c.SendFile("/home/kocoder/szuntis-viel-zu-fiel/szuntis-backend/router/home.html", true)
|
||||||
|
})
|
||||||
|
ws.Get("/ws", authMiddleware.IsWebscoketUpgrade, websocket.New(router.Upgrade))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct{}
|
||||||
|
|
||||||
|
var Clients = make(map[*websocket.Conn]Client)
|
||||||
|
var Register = make(chan *websocket.Conn)
|
||||||
|
var Broadcast = make(chan string)
|
||||||
|
var Unregister = make(chan *websocket.Conn)
|
||||||
|
|
||||||
|
func RunHub() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case conn := <-Register:
|
||||||
|
Clients[conn] = Client{}
|
||||||
|
fmt.Println("Connection registered")
|
||||||
|
case message := <-Broadcast:
|
||||||
|
fmt.Println("Recieved BC request: " + message)
|
||||||
|
for connection := range Clients {
|
||||||
|
if err := connection.WriteMessage(websocket.TextMessage, []byte(message)); err != nil {
|
||||||
|
fmt.Println("Write error: ", err)
|
||||||
|
|
||||||
|
Unregister <- connection
|
||||||
|
connection.WriteMessage(websocket.CloseMessage, []byte{})
|
||||||
|
connection.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case connection := <-Unregister:
|
||||||
|
delete(Clients, connection)
|
||||||
|
fmt.Println("Unregistered Connection")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws WebSocketRouter) Upgrade(c *websocket.Conn) {
|
||||||
|
defer func() {
|
||||||
|
fmt.Println(1)
|
||||||
|
Unregister <- c
|
||||||
|
c.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println(2)
|
||||||
|
Register <- c
|
||||||
|
fmt.Println(12)
|
||||||
|
|
||||||
|
for {
|
||||||
|
messageType, message, err := c.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||||
|
fmt.Println("Read error: ", err)
|
||||||
|
}
|
||||||
|
fmt.Println("ASDF")
|
||||||
|
return //Call defered function to close the connection
|
||||||
|
}
|
||||||
|
|
||||||
|
if messageType == websocket.TextMessage {
|
||||||
|
fmt.Println("Messgae", string(message))
|
||||||
|
Broadcast <- string(message)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Websocket message received of type: ", messageType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
tmp/build-errors.log
Normal file
1
tmp/build-errors.log
Normal file
|
@ -0,0 +1 @@
|
||||||
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|
Loading…
Reference in New Issue
Block a user