feat: qr-code api, major refactor, objectGUID as user id and group id
Build and Push Docker image / build-and-push (push) Failing after 29s
Details
Build and Push Docker image / build-and-push (push) Failing after 29s
Details
This commit is contained in:
parent
382388eb91
commit
d51a92f6e1
|
@ -1,5 +1,6 @@
|
|||
.env.local
|
||||
.gitignore
|
||||
.gitlab-ci.yml
|
||||
.gitea
|
||||
.pb_data
|
||||
docker-compose.yml
|
||||
Readme.md
|
||||
Readme.md
|
|
@ -0,0 +1,32 @@
|
|||
name: Build and Push Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Log in to StuVe Gitea Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: git.stuve.uni-ulm.de
|
||||
username: ${{ secrets.USER_NAME }}
|
||||
password: ${{ secrets.USER_PASSWORD }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend:latest
|
||||
|
||||
#- name: Trigger webhook
|
||||
# run: curl -X POST ${{ secrets.WEBHOOK_URL }}
|
|
@ -10,6 +10,7 @@ pb_data
|
|||
|
||||
# env
|
||||
*.env.local
|
||||
*.env
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
|
@ -1,15 +0,0 @@
|
|||
stages:
|
||||
- build
|
||||
|
||||
build-container:
|
||||
stage: build
|
||||
image:
|
||||
name: gcr.io/kaniko-project/executor:debug
|
||||
entrypoint: [ "" ]
|
||||
script:
|
||||
- /kaniko/executor
|
||||
--context "${CI_PROJECT_DIR}"
|
||||
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
||||
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
|
||||
only:
|
||||
- main
|
|
@ -2,6 +2,10 @@
|
|||
# This is the first stage of a multi-stage build.
|
||||
FROM golang:1.19 as builder
|
||||
|
||||
# Set labels
|
||||
LABEL maintainer="Valentin Kolb"
|
||||
LABEL version="1.0"
|
||||
|
||||
# Set the working directory inside the container.
|
||||
WORKDIR /build
|
||||
|
||||
|
|
87
Readme.md
87
Readme.md
|
@ -3,7 +3,7 @@
|
|||
## Übersicht
|
||||
|
||||
Als Backend für die StuVe IT Tools wird [Pocketbase](https://pocketbase.io)
|
||||
verwendet. Pocketbase ist ein Backend-as-a-Service, der auf SQLite basiert.
|
||||
verwendet. Pocketbase ist ein self-hosted Backend-as-a-Service, der auf SQLite basiert.
|
||||
|
||||
## Was ist Pocketbase?
|
||||
|
||||
|
@ -54,9 +54,9 @@ Funktionen für die einzelnen Tabellen und User erlaubt sind.
|
|||
## Entwickeln
|
||||
|
||||
```bash
|
||||
git clone ...
|
||||
cd backend
|
||||
go run main.go serve # --debug=0 for no debug output
|
||||
git clone https://git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend.git
|
||||
cd stuve-it-backend
|
||||
go run main/main.go serve # --debug=0 for no debug output
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
@ -84,8 +84,10 @@ Die einzelnen custom go Packages sind weiter unten beschrieben.
|
|||
│ ├── models.go # Structs für LDAP User und Group
|
||||
│ ├── tables.go # Erstellt die benötigten Tabellen in der Datenbank (Users, Groups, Logs)
|
||||
│ └── ldapSync.go # Sync Funktionen (Sync Users, Groups, ...)
|
||||
└── ldapLogin # LDAP Login Package
|
||||
└── main.go # Login Funktionen (Login Route)
|
||||
├── ldapLogin # LDAP Login Package
|
||||
│ └── main.go # Login Funktionen (Login Route)
|
||||
└── qrApi # QR API Package
|
||||
└── main.go # Api Route
|
||||
```
|
||||
|
||||
## Custom Packages
|
||||
|
@ -98,7 +100,46 @@ wurden einige Packages erstellt, die Pocketbase erweitern.
|
|||
Das Logger Package ist ein custom Logger, der die Log-Nachrichten
|
||||
farblich in die Konsole schreibt.
|
||||
Diese Package ist sehr minimal gehalten und bietet nur die
|
||||
Funktionen `Info`, `Warn` und `Error` an.
|
||||
Funktionen `Success`, `Info` und `Error` an.
|
||||
|
||||
#### Beispiel
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
|
||||
func main() {
|
||||
logger.LogInfoF("Info Message")
|
||||
logger.LogErrorF("Warn Message")
|
||||
logger.LogErrorF("Error Message")
|
||||
}
|
||||
```
|
||||
|
||||
### QR API
|
||||
|
||||
Das QR API Package ist ein einfaches Package, das eine API Route
|
||||
zum Generieren von QR-Codes in SVG anbietet.
|
||||
|
||||
#### API Route
|
||||
|
||||
Das Package bietet die Route `GET /api/qr/v1` an, welche die folgenden
|
||||
Parameter als json entgegennimmt:
|
||||
|
||||
| Parameter | Datentyp | Beschreibung |
|
||||
|-------------------|-------------|------------------------------------------------------------------------------------------------|
|
||||
| `data` | string | Der Text, der im QR-Code codiert werden soll (**required**) |
|
||||
| `ecc` | string-enum | Der Error Correction Level des QR-Codes (`L`, `M` - default, `Q`, `H`) |
|
||||
| `scale` | int | Der Scale des QR-Codes (default `1`) |
|
||||
| `border` | int | Der Border des QR-Codes (default `1`), eine Border Uni ist die Größe von einem QR-Code 'pixel' |
|
||||
| `color` | hex-string | Die Farbe des QR-Codes (default `#000000`) |
|
||||
| `colorBackground` | hex-string | Die Hintergrundfarbe des QR-Codes (default `#FFFFFF`) |
|
||||
|
||||
#### Beispiel
|
||||
|
||||
```bash
|
||||
curl -X GET https://it.stuve.uni-ulm.de/api/qr/v1 -d '{"data": "https://stuve.uni-ulm.de"}'
|
||||
```
|
||||
|
||||
### LDAP Sync
|
||||
|
||||
|
@ -108,6 +149,36 @@ die LDAP Datenbank mit der Pocketbase Datenbank.
|
|||
Dabei werden alle LDAP User und Gruppen in die Pocketbase Datenbank
|
||||
kopiert.
|
||||
|
||||
Dieses Package erfordert, dass alle Gruppen und User das Attribut `objectGUID` haben. Dies ist in der Regel bei Windows
|
||||
ADs der Fall.
|
||||
|
||||
#### LDAP Attribute
|
||||
|
||||
Die folgenden LDAP Attribute werden in der Pocketbase Datenbank gespeichert.
|
||||
|
||||
##### User
|
||||
|
||||
| Attribut | Pocketbase Name | Beschreibung |
|
||||
|----------------|--------------------------------------------|-------------------------------------------------------------------|
|
||||
| objectGUID | id | Eindeutige ID des Users (nur die ersten 15 Zeichen werden genutzt |
|
||||
| givenName | givenName | Vorname des Users |
|
||||
| sn | sn | Nachname des Users |
|
||||
| mail | email | E-Mail des Users |
|
||||
| memberOf | memberOf (in Pocketbase eine SQL Relation) | Gruppenzugehörigkeit des Users |
|
||||
| accountExpires | accountExpires (in Pocketbase UTC) | Account Ablaufdatum |
|
||||
| dn | dn | Distinguished Name des Users |
|
||||
| cn | cn & username | Common Name des Users |
|
||||
|
||||
##### Group
|
||||
|
||||
| Attribut | Pocketbase Name | Beschreibung |
|
||||
|-------------|--------------------------------------------|--------------------------------------------------------------------|
|
||||
| objectGUID | id | Eindeutige ID der Gruppe (nur die ersten 15 Zeichen werden genutzt |
|
||||
| cn | cn | Common Name der Gruppe |
|
||||
| dn | dn | Distinguished Name der Gruppe |
|
||||
| description | description | Beschreibung der Gruppe |
|
||||
| memberOf | memberOf (in Pocketbase eine SQL Relation) | Gruppenzugehörigkeit der Gruppe |
|
||||
|
||||
#### Konfiguration
|
||||
|
||||
Das Package benötigt folgende ENV Variablen:
|
||||
|
@ -147,7 +218,7 @@ noch nicht existiert. In diesem Fall wird die Beziehung erst beim
|
|||
nächsten Sync erstellt. Falls eine `memberOf` Gruppe nicht gefunden wird,
|
||||
wird dies in der Konsole geloggt.
|
||||
|
||||
Für jede Synchronisation wird ein Log in der `ldap_sync_logs` Tabelle
|
||||
Für jede Synchronisation wird ein Log-in der `ldap_sync_logs` Tabelle
|
||||
erstellt.
|
||||
|
||||
Sowohl für die ldap_users als auch für die ldap_groups Tabelle wird
|
||||
|
|
13
go.mod
13
go.mod
|
@ -1,9 +1,14 @@
|
|||
module gitlab.uni-ulm.de/stuve-it/it-tools/backend
|
||||
module git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend
|
||||
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
|
||||
github.com/pocketbase/dbx v1.10.1
|
||||
github.com/pocketbase/pocketbase v0.19.0
|
||||
)
|
||||
|
||||
|
@ -34,7 +39,6 @@ require (
|
|||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/ganigeorgiev/fexpr v0.3.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
|
@ -43,23 +47,20 @@ require (
|
|||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/google/wire v0.5.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.17 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/pocketbase/dbx v1.10.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/cobra v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/testify v1.8.4 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -207,8 +207,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
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/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
|
|
|
@ -2,13 +2,13 @@ package ldapLogin
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/ldapSync"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/ldapSync"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
|
|
@ -6,11 +6,11 @@ this file contains functions to sync ldap users and groups to the database
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/forms"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger"
|
||||
)
|
||||
|
||||
// upsertLDAPGroup This function creates / updates a record in the ldap groups table
|
||||
|
@ -27,8 +27,8 @@ func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error {
|
|||
// if record exists, update it
|
||||
if res, _ := app.Dao().FindFirstRecordByFilter(
|
||||
ldapGroupsTableName,
|
||||
"gidNumber = {:gidNumber}",
|
||||
dbx.Params{"gidNumber": ldapGroup.gidNumber},
|
||||
"id = {:id}",
|
||||
dbx.Params{"id": ldapGroup.id},
|
||||
); res != nil {
|
||||
record = res
|
||||
} else { // if record does not exist, create it
|
||||
|
@ -51,7 +51,7 @@ func upsertLDAPGroup(app *pocketbase.PocketBase, ldapGroup *LDAPGroup) error {
|
|||
|
||||
// load data
|
||||
err = form.LoadData(map[string]any{
|
||||
"gidNumber": ldapGroup.gidNumber,
|
||||
"id": ldapGroup.id,
|
||||
"cn": ldapGroup.cn,
|
||||
"dn": ldapGroup.dn,
|
||||
"description": ldapGroup.description,
|
||||
|
@ -83,8 +83,8 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error {
|
|||
// if record exists, update it
|
||||
if res, _ := app.Dao().FindFirstRecordByFilter(
|
||||
ldapUsersTableName,
|
||||
"uidNumber = {:uidNumber}",
|
||||
dbx.Params{"uidNumber": ldapUser.uidNumber},
|
||||
"id = {:id}",
|
||||
dbx.Params{"id": ldapUser.id},
|
||||
); res != nil {
|
||||
record = res
|
||||
} else { // if record does not exist, create it
|
||||
|
@ -111,7 +111,7 @@ func upsertLDAPUser(app *pocketbase.PocketBase, ldapUser *LDAPUser) error {
|
|||
}
|
||||
}
|
||||
|
||||
record.Set("uidNumber", ldapUser.uidNumber)
|
||||
record.Set("id", ldapUser.id)
|
||||
record.Set("givenName", ldapUser.givenName)
|
||||
record.Set("sn", ldapUser.sn)
|
||||
record.Set("username", ldapUser.cn)
|
||||
|
|
|
@ -3,12 +3,13 @@ package ldapSync
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/forms"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
@ -20,6 +21,21 @@ type SyncResult struct {
|
|||
Errors []error
|
||||
}
|
||||
|
||||
// getObjectGUID This function gets the objectGUID from an ldap entry
|
||||
//
|
||||
// since the objectGUID is a binary value, it is returned as a string (uuid)
|
||||
func getObjectGUID(entry *ldap.Entry) (string, error) {
|
||||
// get the objectGUID
|
||||
var bytes = entry.GetRawAttributeValue("objectGUID")
|
||||
|
||||
// convert to uuid
|
||||
u, err := uuid.FromBytes(bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return u.String()[:15], nil // only use the first 15 characters of the uuid
|
||||
}
|
||||
|
||||
// upsertLDAPGroup This function creates / updates a record in the ldap groups table
|
||||
//
|
||||
// this function expects that the table ldapGroups already exists
|
||||
|
@ -34,7 +50,7 @@ func syncLdapGroups(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResul
|
|||
os.Getenv("LDAP_GROUP_BASE_DN"), // The base dn to search
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
os.Getenv("LDAP_GROUP_FILTER"), // The filter to apply
|
||||
[]string{"gidNumber", "description", "dn", "cn", "msSFU30NisDomain", "memberOf"},
|
||||
[]string{"description", "dn", "cn", "msSFU30NisDomain", "memberOf", "objectGUID"},
|
||||
nil,
|
||||
)
|
||||
|
||||
|
@ -46,8 +62,15 @@ func syncLdapGroups(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResul
|
|||
}
|
||||
|
||||
for _, entry := range groupsFoundInLdap.Entries {
|
||||
|
||||
var id, e = getObjectGUID(entry)
|
||||
|
||||
if e != nil {
|
||||
errors = append(errors, fmt.Errorf("unable to get objectGUID for group with dn: %s - %s", entry.DN, e))
|
||||
}
|
||||
|
||||
err := upsertLDAPGroup(app, &LDAPGroup{
|
||||
gidNumber: entry.GetAttributeValue("gidNumber"),
|
||||
id: id,
|
||||
description: entry.GetAttributeValue("description"),
|
||||
dn: entry.DN,
|
||||
cn: entry.GetAttributeValue("cn"),
|
||||
|
@ -115,7 +138,7 @@ func syncLdapUsers(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResult
|
|||
os.Getenv("LDAP_BASE_DN"), // The base dn to search
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
os.Getenv("LDAP_USER_FILTER"), // The filter to apply
|
||||
[]string{"givenName", "sn", "accountExpires", "uidNumber", "mail", "dn", "cn", "msSFU30NisDomain", "memberOf"},
|
||||
[]string{"givenName", "sn", "accountExpires", "mail", "dn", "cn", "msSFU30NisDomain", "memberOf", "objectGUID"},
|
||||
nil,
|
||||
)
|
||||
|
||||
|
@ -127,11 +150,18 @@ func syncLdapUsers(app *pocketbase.PocketBase, ldapClient *ldap.Conn) SyncResult
|
|||
}
|
||||
|
||||
for _, entry := range usersFoundInLdap.Entries {
|
||||
|
||||
var id, e = getObjectGUID(entry)
|
||||
|
||||
if e != nil {
|
||||
errors = append(errors, fmt.Errorf("unable to get objectGUID for user with dn: %s - %s", entry.DN, e))
|
||||
}
|
||||
|
||||
err := upsertLDAPUser(app, &LDAPUser{
|
||||
givenName: entry.GetAttributeValue("givenName"),
|
||||
sn: entry.GetAttributeValue("sn"),
|
||||
accountExpires: entry.GetAttributeValue("accountExpires"),
|
||||
uidNumber: entry.GetAttributeValue("uidNumber"),
|
||||
id: id,
|
||||
mail: entry.GetAttributeValue("mail"),
|
||||
dn: entry.DN,
|
||||
cn: entry.GetAttributeValue("cn"),
|
||||
|
|
|
@ -5,9 +5,9 @@ package ldapSync
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/tools/cron"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/logger"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
@ -88,7 +88,7 @@ func InitLdapSync(app *pocketbase.PocketBase) error {
|
|||
|
||||
ldapSyncSchedule := os.Getenv("LDAP_SYNC_SCHEDULE")
|
||||
|
||||
// syncs ldap every 2 minutes
|
||||
// syncs ldap - interval specified in the LDAP_SYNC_SCHEDULE env variable
|
||||
scheduler.MustAdd("ldapSync", ldapSyncSchedule, func() {
|
||||
logger.LogInfoF("syncing LDAP ...")
|
||||
syncLdap(app)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package ldapSync
|
||||
|
||||
type LDAPUser struct {
|
||||
id string
|
||||
givenName string
|
||||
sn string
|
||||
accountExpires string
|
||||
uidNumber string
|
||||
mail string
|
||||
|
||||
dn string
|
||||
|
@ -14,7 +14,7 @@ type LDAPUser struct {
|
|||
}
|
||||
|
||||
type LDAPGroup struct {
|
||||
gidNumber string
|
||||
id string
|
||||
description string
|
||||
|
||||
dn string
|
||||
|
|
|
@ -33,13 +33,6 @@ func createLDAPGroupsTable(app *pocketbase.PocketBase) error {
|
|||
form.UpdateRule = nil
|
||||
form.DeleteRule = nil
|
||||
|
||||
// add group ID field
|
||||
form.Schema.AddField(&schema.SchemaField{
|
||||
Name: "gidNumber",
|
||||
Type: schema.FieldTypeText,
|
||||
Required: true,
|
||||
})
|
||||
|
||||
// add description field
|
||||
form.Schema.AddField(&schema.SchemaField{
|
||||
Name: "description",
|
||||
|
@ -64,7 +57,7 @@ func createLDAPGroupsTable(app *pocketbase.PocketBase) error {
|
|||
|
||||
// create index on cn
|
||||
form.Indexes = types.JsonArray[string]{
|
||||
"CREATE UNIQUE INDEX idx_ldapGroups ON " + ldapGroupsTableName + " (cn, gidNumber, dn)",
|
||||
"CREATE UNIQUE INDEX idx_ldapGroups ON " + ldapGroupsTableName + " (cn, dn)",
|
||||
}
|
||||
|
||||
// validate and submit (internally it calls app.Dao().SaveCollection(collection) in a transaction)
|
||||
|
@ -144,13 +137,6 @@ func createLDAPUsersTable(app *pocketbase.PocketBase) error {
|
|||
Required: true,
|
||||
})
|
||||
|
||||
// add uidNumber field
|
||||
form.Schema.AddField(&schema.SchemaField{
|
||||
Name: "uidNumber",
|
||||
Type: schema.FieldTypeText,
|
||||
Required: true,
|
||||
})
|
||||
|
||||
// add surname field
|
||||
form.Schema.AddField(&schema.SchemaField{
|
||||
Name: "sn",
|
||||
|
@ -185,7 +171,7 @@ func createLDAPUsersTable(app *pocketbase.PocketBase) error {
|
|||
|
||||
// create index on username
|
||||
form.Indexes = types.JsonArray[string]{
|
||||
"CREATE UNIQUE INDEX idx_ldapUsers ON " + ldapGroupsTableName + " (cn, uidNumber, dn)",
|
||||
"CREATE UNIQUE INDEX idx_ldapUsers ON " + ldapGroupsTableName + " (cn, dn)",
|
||||
}
|
||||
|
||||
return form.Submit()
|
||||
|
|
21
main/main.go
21
main/main.go
|
@ -1,19 +1,27 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/ldapLogin"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/ldapSync"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/qrApi"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/ldapLogin"
|
||||
"gitlab.uni-ulm.de/stuve-it/it-tools/backend/ldapSync"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// load env
|
||||
godotenv.Load(".env.local")
|
||||
godotenv.Load(".env")
|
||||
err := godotenv.Load(".env.local")
|
||||
if err != nil {
|
||||
logger.LogInfoF("The file '.env.local' could not be loaded.")
|
||||
}
|
||||
err = godotenv.Load(".env")
|
||||
if err != nil {
|
||||
logger.LogInfoF("The file '.env' could not be loaded.")
|
||||
}
|
||||
|
||||
// create app
|
||||
app := pocketbase.New()
|
||||
|
@ -28,6 +36,11 @@ func main() {
|
|||
return ldapLogin.InitLDAPLogin(app, e)
|
||||
})
|
||||
|
||||
// setup qr api
|
||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
return qrApi.InitQRApi(app, e)
|
||||
})
|
||||
|
||||
// start app
|
||||
if err := app.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package qrApi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
goqr "git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/go-qr"
|
||||
"git.stuve.uni-ulm.de/StuVe-IT/stuve-it-backend/logger"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"io"
|
||||
)
|
||||
|
||||
// InitQRApi initializes ar code api endpoint
|
||||
//
|
||||
// this endpoint can be used to create qr codes
|
||||
// GET /api/qr/v1
|
||||
//
|
||||
// the endpoint expects the following request data:
|
||||
//
|
||||
// {
|
||||
// "data": "what to be encoded",
|
||||
// "ecc": "error correction level ('L', 'M' (default), 'Q', 'H')",
|
||||
// "scale": "scale of qr code (default 1), must be greater than 0",
|
||||
// "border": "border of qr code (default 1), must be equal or greater than 0, one is equal to one qr-code 'pixel'"
|
||||
// "color": "color of qr code (default #000000)"
|
||||
// "colorBackground": "background color of qr code (default #FFFFFF)",
|
||||
// }
|
||||
//
|
||||
// if the user is authenticated successfully the endpoint returns and apis.RecordAuthResponse
|
||||
func InitQRApi(app *pocketbase.PocketBase, e *core.ServeEvent) error {
|
||||
|
||||
// add endpoint to app
|
||||
logger.LogInfoF("Adding QR API Endpoint")
|
||||
|
||||
e.Router.GET("/api/qr/v1", func(c echo.Context) error {
|
||||
|
||||
// get data from request
|
||||
data := struct {
|
||||
Data string `json:"data"`
|
||||
ECC string `json:"ecc"`
|
||||
Scale int `json:"scale"`
|
||||
Border int `json:"border"`
|
||||
ColorDark string `json:"color"`
|
||||
ColorLight string `json:"colorBackground"`
|
||||
}{}
|
||||
if err := c.Bind(&data); err != nil {
|
||||
return apis.NewBadRequestError("Failed to read request data", err)
|
||||
}
|
||||
|
||||
// get correct error correction level
|
||||
var errCorLvl goqr.Ecc
|
||||
switch data.ECC {
|
||||
case "L":
|
||||
errCorLvl = goqr.Low
|
||||
case "M":
|
||||
errCorLvl = goqr.Medium
|
||||
case "Q":
|
||||
errCorLvl = goqr.Quartile
|
||||
case "H":
|
||||
errCorLvl = goqr.High
|
||||
default:
|
||||
errCorLvl = goqr.Medium
|
||||
}
|
||||
|
||||
// encode data to qr code
|
||||
qrCode, err := goqr.EncodeText(data.Data, errCorLvl)
|
||||
if err != nil {
|
||||
return apis.NewBadRequestError("Failed to encode data to qr code", err)
|
||||
}
|
||||
|
||||
// set default scale and border
|
||||
scale := data.Scale
|
||||
border := data.Border
|
||||
if scale == 0 {
|
||||
scale = 1
|
||||
}
|
||||
if border == 0 {
|
||||
border = 1
|
||||
}
|
||||
config := goqr.NewQrCodeImgConfig(scale, border)
|
||||
|
||||
// create new buffer and writer
|
||||
var buffer bytes.Buffer
|
||||
writer := io.Writer(&buffer)
|
||||
|
||||
// set default colors
|
||||
colorLight := data.ColorLight
|
||||
colorDark := data.ColorDark
|
||||
if colorLight == "" {
|
||||
colorLight = "#FFFFFF"
|
||||
}
|
||||
if colorDark == "" {
|
||||
colorDark = "#000000"
|
||||
}
|
||||
|
||||
// write qr code to buffer
|
||||
err = qrCode.WriteAsSVG(config, writer, colorLight, colorDark)
|
||||
|
||||
// return error if writing qr code to buffer fails
|
||||
if err != nil {
|
||||
logger.LogErrorF("Failed to write QR Code: %e", err)
|
||||
return apis.NewBadRequestError("Failed to write QR Code", err)
|
||||
}
|
||||
|
||||
// return qr code as svg
|
||||
return c.Stream(200, "image/svg+xml", io.Reader(&buffer))
|
||||
}, apis.ActivityLogger(app))
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue