Compare commits

...
84 Commits
Author SHA1 Message Date
Bernd-Rodler b01ba5397e chore: retag product images to vnclagoon/* (#2)
Build + push image / build-and-push (push) Successful in 4m48s
2026-08-20 09:19:20 +00:00
macanhhuy 97e6fb83b5 build: migrate CI to Gitea Actions, drop GitLab/Jenkins/GCP
Build + push image / build-and-push (push) Failing after 16s
2026-08-19 19:44:14 +07:00
Stefan-Sanger 9a1d260afe fix: upgrade deprecated nodejs usage
Part-of: <http://gitlab.vnc.biz/uxf/vnc-hybridauth2/-/merge_requests/23>
2026-06-29 11:20:00 +02:00
Stefan-Sanger d4c9b722d2 fix: remove unused deb build stage 2026-06-11 15:03:50 +02:00
marge f7b5a35bee Merge branch 'rootless' into 'master'
fix: upgrade alpine, prepare rootless op

See merge request uxf/vnc-hybridauth2!22
2026-06-11 12:59:48 +00:00
Stefan-Sanger 0553d08007 fix: upgrade alpine, prepare rootless op
Part-of: <http://gitlab.vnc.biz/uxf/vnc-hybridauth2/-/merge_requests/22>
2026-06-11 14:58:31 +02:00
Stefan-Sanger c68a482c29 fix: add header for NC unauthed 2025-10-01 15:29:35 +02:00
Stefan-Sanger fcc2a9a003 fix: add headers for NC integration 2025-10-01 14:53:34 +02:00
Stefan-Sanger da0e3108ca fix: container label 2024-08-05 07:43:27 +02:00
Stefan-Sanger efdba4ccc2 fix: remove label 2024-08-05 07:38:16 +02:00
Stefan-Sanger 6915b7d230 fix: rebuild 2024-08-05 07:35:12 +02:00
Stefan-Sanger 24297a1206 fix: declare label for public container registry 2024-08-05 07:31:03 +02:00
Stefan-Sanger be70f43151 Merge branch 'fix-org-lock' into 'master'
fix: org based locking

See merge request uxf/vnc-hybridauth2!21
2024-04-24 14:08:19 +00:00
Stefan-Sanger a89b8821c8 fix: org based locking 2024-04-24 16:07:48 +02:00
Stefan-Sanger 5dfe2d1fb8 Merge branch 'fix-org-lock' into 'master'
fix: build issue

See merge request uxf/vnc-hybridauth2!20
2024-04-24 11:55:09 +00:00
Stefan-Sanger 6377554897 fix: build issue 2024-04-24 13:54:42 +02:00
Stefan-Sanger c24e66369a Merge branch 'fix-org-lock' into 'master'
fix: org lock

See merge request uxf/vnc-hybridauth2!19
2024-04-24 11:50:33 +00:00
Stefan-Sanger ae254fe7dd fix: org lock 2024-04-24 13:49:39 +02:00
Stefan-Sanger da456449b8 fix: audit 2023-06-28 10:30:22 +02:00
Stefan-Sanger 43ee1de9af fix: config template 2022-10-05 18:52:53 +02:00
Stefan-Sanger 28231a81b4 fix: config template 2022-10-05 18:33:51 +02:00
Stefan-Sanger 62de556327 fix: add option to disable tls 2022-10-05 17:41:24 +02:00
Stefan-Sanger 24413e64b0 fix: typo 2022-08-27 12:56:46 +02:00
Stefan-Sanger 977332680c fix: use trivy from vnc-runner 2022-08-27 12:54:39 +02:00
Stefan-Sanger d9ad874401 Revert "fix: cleanup"
This reverts commit 26aecd3264.
2022-08-27 12:45:39 +02:00
Stefan-Sanger 26aecd3264 fix: cleanup 2022-08-27 12:41:10 +02:00
Stefan-Sanger 90f2b53d1c fix: trivy execution 2022-08-27 12:38:39 +02:00
Stefan-Sanger 6812a952b8 fix: trivy execution 2022-08-27 12:35:26 +02:00
Stefan-Sanger 9437fb2878 fix: add trivy 2022-08-27 12:25:36 +02:00
Stefan-Sanger 698ef50288 debug info 2022-08-27 12:13:32 +02:00
Stefan-Sanger b7e8045b22 Merge branch 'fix-audit' into 'master'
fix: build issue

See merge request uxf/vnc-hybridauth2!18
2022-08-27 09:49:33 +00:00
Stefan-Sanger 8dc7de8944 fix: build issue 2022-08-27 11:49:16 +02:00
Stefan-Sanger 32fed53f5a Merge branch 'fix-audit' into 'master'
Fix audit

See merge request uxf/vnc-hybridauth2!17
2022-08-27 09:47:15 +00:00
Stefan-Sanger 96b32f385e fix: cleanup 2022-08-27 11:46:43 +02:00
Stefan-Sanger e50b60be8e fix: update dependencies, switch to alpine 2022-08-27 11:45:06 +02:00
Leonidas Apostolidis e1172afaa4 Merge branch 'auto-releases' into 'master'
Update .gitlab-ci.yml

See merge request uxf/vnc-hybridauth2!16
2021-10-21 09:39:42 +00:00
Leonidas Apostolidis 6fef2007d4 Update .gitlab-ci.yml 2021-10-21 10:38:59 +01:00
Leonidas Apostolidis 799dc363f5 Merge branch 'leoapost-master-patch-26663' into 'master'
Fix the CI DEV_CONTAINER_REGISTRY var

See merge request uxf/vnc-hybridauth2!15
2021-10-19 21:19:18 +00:00
Leonidas Apostolidis 978bd95afe Fix the CI DEV_CONTAINER_REGISTRY var 2021-10-19 21:19:06 +00:00
Leonidas Apostolidis ab99896b1e Merge branch 'auto-releases' into 'master'
Fix the CI prod and stable image tag vars

See merge request uxf/vnc-hybridauth2!14
2021-10-19 21:05:55 +00:00
Leonidas Apostolidis f9e86c50c6 Fix the CI prod and stable image tag vars 2021-10-19 22:05:08 +01:00
Leonidas Apostolidis 6acd1824f9 Merge branch 'auto-releases' into 'master'
Update the CI prod and stable tags

See merge request uxf/vnc-hybridauth2!13
2021-10-19 20:56:42 +00:00
Leonidas Apostolidis ee087eb744 Update the CI prod and stable tags 2021-10-19 21:53:38 +01:00
Leonidas Apostolidis 3cf7def67a Merge branch 'gitlab-ci' into 'master'
Migrate the Jenkins pipeline to Gitlab CI

See merge request uxf/vnc-hybridauth2!12
2021-09-14 21:33:12 +00:00
Leonidas Apostolidis 0a0aef8712 Migrate the Jenkins pipeline to Gitlab CI 2021-09-14 22:32:49 +01:00
Stefan-Sanger ace9e436ee fix: remove factorypackages from Jenkinsfile 2021-09-14 07:40:58 +02:00
Stefan-Sanger 45d0cf7061 fix: cloudsql psql tls issue 2021-09-14 07:31:18 +02:00
Leonidas Apostolidis 978d905bd9 Merge branch 'gitlab-ci' into 'master'
Add a notification CI job for successful or failed pipelines

See merge request uxf/vnc-hybridauth2!11
2021-09-13 21:15:18 +00:00
Leonidas Apostolidis 8b8da3534b Add a notification CI job for successful or failed pipelines 2021-09-13 22:14:17 +01:00
daniel merron 8f79886eb8 Update .gitlab-ci.yml file 2021-08-02 15:40:46 +00:00
daniel merron 3d9b4a1964 Update .gitlab-ci.yml file 2021-08-02 15:37:29 +00:00
daniel merron 4bc46dd8d1 Update .gitlab-ci.yml file 2021-08-02 15:35:32 +00:00
daniel merron 311df6c79b Update .gitlab-ci.yml file 2021-08-02 15:34:08 +00:00
daniel merron 3e7de5a626 Update .gitlab-ci.yml file 2021-08-02 15:28:51 +00:00
daniel merron 54451a32a7 Update .gitlab-ci.yml file 2021-08-02 15:28:48 +00:00
daniel merron b7809a683b Update .gitlab-ci.yml file 2021-08-02 15:26:46 +00:00
Ben Neill f8ca647e75 Update .gitlab-ci.yml 2021-03-28 21:27:14 +00:00
daniel merron 5bac7cd4f0 Merge branch 'docker' into 'master'
updated pipeline to push saas image

See merge request uxf/vnc-hybridauth2!10
2021-03-23 11:06:07 +00:00
Dan Merron 6af53ab82e updated pipeline to push saas image 2021-03-23 11:04:42 +00:00
daniel merron 2b2b424dec Merge branch 'docker' into 'master'
updated dockerfile

See merge request uxf/vnc-hybridauth2!9
2021-03-22 13:03:51 +00:00
Dan Merron c86a100575 updated dockerfile 2021-03-22 13:03:40 +00:00
daniel merron 331b602e86 Merge branch 'docker' into 'master'
fixed pipeline

See merge request uxf/vnc-hybridauth2!8
2021-03-21 18:36:49 +00:00
Dan Merron 5fce11bc69 fixed pipeline 2021-03-21 18:36:42 +00:00
daniel merron 744a26316a Merge branch 'docker' into 'master'
updated pipeline

See merge request uxf/vnc-hybridauth2!7
2021-03-21 18:34:04 +00:00
Dan Merron 37f2179f28 updated pipeline 2021-03-21 18:33:55 +00:00
daniel merron 9fb8e2f6e4 Merge branch 'docker' into 'master'
renamed gitlab ci

See merge request uxf/vnc-hybridauth2!6
2021-03-21 18:32:57 +00:00
Dan Merron b10596c0c6 renamed gitlab ci 2021-03-21 18:32:47 +00:00
daniel merron 0e95f1cb7b Merge branch 'docker' into 'master'
added docker for hybrid auth

See merge request uxf/vnc-hybridauth2!5
2021-03-21 18:32:08 +00:00
Dan Merron a30daf40dc added docker for hybrid auth 2021-03-21 18:31:43 +00:00
Stefan-Sanger 2f228a0bd7 fix: add health check 2021-03-21 19:29:27 +01:00
Ben Neill 3bbfdbdb83 Merge branch 'gcp-deb-repo' into 'master'
Import the .deb package to the GCP deb repository

See merge request uxf/vnc-hybridauth2!4
2021-03-05 22:19:40 +00:00
Leonidas Apostolidis 3e2e1301b8 Import the .deb package to the GCP deb repository 2021-03-05 21:35:36 +00:00
Stefan-Sanger 7bd09115da fix: noldap 2021-02-19 12:25:08 +01:00
Stefan-Sanger fc602853a8 fix: log verbosity 2020-11-20 10:44:35 +01:00
Stefan-Sanger 3579f248f2 Merge branch 'review-dev-vnctask' 2020-10-08 15:47:20 +02:00
Stefan-Sanger 87051c6ccb fix: response payload - https://redmine.vnc.biz/issues/96981 2020-10-08 15:42:25 +02:00
Stefan-Sanger 3af1eefd04 Merge branch 'master' into review-dev-vnctask 2020-10-08 14:50:40 +02:00
Stefan-Sanger 48230b96f9 updated dev config for gcp 2020-10-08 14:44:41 +02:00
Stefan-Sanger f181bd6428 fix: untar stashed modules 2020-07-29 03:32:40 +02:00
Stefan-Sanger be761d99fd fix: create node modules on agent 2020-07-29 03:30:18 +02:00
Stefan-Sanger c283a75fc8 Merge branch 'master-login2fa' into 'master'
fix: domain is not parsed.

See merge request uxf/vnc-hybridauth2!3
2020-05-05 03:30:03 +02:00
Stefan-Sanger 6a70b3d4f5 Merge branch 'master-login2fa' into 'master'
add new endpoint for login2fa

See merge request uxf/vnc-hybridauth2!2
2020-05-04 13:36:35 +02:00
Stefan-Sanger 916570e50e Merge branch 'master' into review-dev-vnctask 2020-04-14 07:55:20 +02:00
Stefan-Sanger 9b99688cfc fix: integrate changes for vnctask / vnctalk with directory 2020-04-14 07:51:20 +02:00
14 changed files with 1316 additions and 801 deletions
+10
View File
@@ -0,0 +1,10 @@
.git
.gitlab-ci.yml
Jenkinsfile.deprecated
startgcpdevapi.sh
.gitea
node_modules
scan
debian
tools
*.tgz
+61
View File
@@ -0,0 +1,61 @@
name: Build + push image
on:
push:
branches: [master]
workflow_dispatch:
env:
REGISTRY: gitea.saas.vnc.biz
IMAGE: gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api
jobs:
build-and-push:
runs-on: ubuntu-latest
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Compute image tag
run: |
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-8)
echo "SHORT_SHA=${SHORT_SHA}" >> $GITHUB_ENV
# kaniko builds straight from a Dockerfile and pushes to the registry, running
# as a static binary inside the job container — the runner has no Docker daemon.
- name: Fetch kaniko (daemon-less image builder)
run: |
set -euo pipefail
curl -fsSL -o /tmp/crane.tgz \
https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Linux_x86_64.tar.gz
tar -xzf /tmp/crane.tgz -C /usr/local/bin crane
mkdir -p /tmp/kaniko-root
crane export gcr.io/kaniko-project/executor:debug /tmp/kaniko-fs.tar
tar -xf /tmp/kaniko-fs.tar -C /tmp/kaniko-root
cp /tmp/kaniko-root/kaniko/executor /usr/local/bin/kaniko-executor
chmod +x /usr/local/bin/kaniko-executor
/usr/local/bin/kaniko-executor version
# kaniko's push auth reads $DOCKER_CONFIG/config.json (go-containerregistry
# authn.DefaultKeychain). Write to both locations and export DOCKER_CONFIG so
# auth is picked up regardless of how $HOME resolves.
- name: Configure registry auth for push
run: |
AUTH=$(printf '%s:%s' "${REGISTRY_USER}" "${REGISTRY_TOKEN}" | base64 -w0)
CFG=$(printf '{"auths":{"%s":{"auth":"%s"}}}' "${REGISTRY}" "${AUTH}")
mkdir -p /kaniko/.docker "$HOME/.docker"
printf '%s' "$CFG" > /kaniko/.docker/config.json
printf '%s' "$CFG" > "$HOME/.docker/config.json"
echo "DOCKER_CONFIG=/kaniko/.docker" >> "$GITHUB_ENV"
# The Dockerfile lives at the repo root; its ADD/COPY paths (app/, package.json,
# yarn.lock, config.js) are relative to the root.
- name: Build + push image
run: |
/usr/local/bin/kaniko-executor \
--context "dir://${GITHUB_WORKSPACE}" \
--dockerfile Dockerfile \
--skip-tls-verify-registry="${REGISTRY}" \
--destination "${IMAGE}:sha-${SHORT_SHA}" \
--destination "${IMAGE}:latest"
+33
View File
@@ -0,0 +1,33 @@
FROM alpine:3.22.4 AS builder
RUN apk update
RUN apk update && apk upgrade && apk add --no-cache make gcc nodejs npm python3 g++ gcc libc-dev expat-dev libxml2-dev libxmlb-dev yarn nodejs-dev && rm -rf /var/cache/apk/*
RUN mkdir -p /usr/share/vnctalk-hybrid-authenticator2
RUN mkdir -p /usr/share/vnctalk-hybrid-authenticator2/config
ADD app /usr/share/vnctalk-hybrid-authenticator2/app
COPY package.json /usr/share/vnctalk-hybrid-authenticator2/package.json
COPY yarn.lock /usr/share/vnctalk-hybrid-authenticator2/yarn.lock
COPY config.js /usr/share/vnctalk-hybrid-authenticator2/config/vnc-hybrid-authenticator.js
RUN cd /usr/share/vnctalk-hybrid-authenticator2 && yarn install
FROM alpine:3.22.4
RUN apk update && apk upgrade && apk add --no-cache nodejs npm expat libxml2 libxmlb && rm -rf /var/cache/apk/*
COPY --from=builder /usr/share/vnctalk-hybrid-authenticator2 /usr/share/vnctalk-hybrid-authenticator2
# Create non-root user and transfer ownership
RUN addgroup -g 1001 vncuser && \
adduser -D -u 1001 -G vncuser vncuser
USER vncuser
LABEL org.opencontainers.image.source=https://github.com/vnc-biz/vnclagoon-images
#RUN npm install /usr/share/vnctalk-hybrid-authenticator2/app
CMD ["node", "/usr/share/vnctalk-hybrid-authenticator2/app/app.js"]
Vendored
-63
View File
@@ -1,63 +0,0 @@
#!groovy
pipeline {
agent none
environment {
git_commit_message = ''
git_commit_diff = ''
git_commit_author = ''
git_commit_author_name = ''
git_commit_author_email = ''
ANDROID_HOME = '/opt/android-sdk/'
}
stages {
stage('Packaging') {
agent {
label 'master'
}
steps {
sh "echo 'Packaging'"
deleteDir()
checkout scm
sh "git fetch --tags"
sh "makechangelog.uxf > debian/changelog"
sh "cat debian/changelog"
sh "mkdir src"
sh "sed -n 1p debian/changelog | grep -oP '\\((.*?)\\)' > src/version.txt"
sh "echo '####################################################'"
sh "cat src/version.txt"
sh "echo '####################################################'"
sh 'rm config/vnc-hybrid-authenticator.js'
sh 'cp -P conf.template/vnc-hybridauth2.js config/vnc-hybrid-authenticator.js'
// yarn fails on node4 with kurento stuff
sh 'yarn install'
lock('debianbuild') {
sh "cd debian; debuild --check-dirname-level 0 --no-tgz-check --no-lintian -kjenkins@vnc.biz -p'gpg --no-tty --passphrase q3tx65wurstbrot'; cd .."
}
sh "mkdir -p ../pkgarchive/"
sh "scp ../*.deb repo@factorypackages.rz.vnc.biz:/srv/repo/apt/incoming/"
sh "ssh repo@factorypackages.rz.vnc.biz /srv/repo/bin/import-new-packages.sh"
sh "mv ../*.deb ../pkgarchive/"
sh "rm ../*.dsc"
sh "rm ../*amd64.build"
sh "rm ../*amd64.changes"
}
}
}
post {
always {
emailext (
to: 'stefan.saenger@vnc.biz',
subject: "${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "Build URL: ${env.BUILD_URL}.",
attachLog: false,
)
}
}
}
+41
View File
@@ -0,0 +1,41 @@
# vnc-hybridauth2 (vnctalk-hybrid-authenticator2)
Hybrid authenticator for VNCtalk / VNCmail. An Express service that sits between the
auth-proxy's `hybridAuthURL` and the directory backends: it authenticates users against
**LDAP** and the **VNCdirectory** PostgreSQL DB, and issues/verifies the XMPP JWT
(`xmppToken`) that Prosody and the mail/talk APIs share for SSO.
Prosody's `mod_auth_http_async` points `hybridaAuthUrl` at this service's HTTP-basic
endpoint (default port `9544`).
## Build & image
Built by Gitea Actions (`.gitea/workflows/deploy.yml`) on every push to `master`, using
kaniko (no Docker daemon on the runner). The image is pushed to the Gitea registry:
- `gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api:latest`
- `gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api:sha-<short-sha>`
Registry auth uses the `REGISTRY_USER` / `REGISTRY_TOKEN` Actions secrets. The image runs
as the non-root `vncuser` (uid 1001) and starts `node /usr/share/vnctalk-hybrid-authenticator2/app/app.js`.
## Configuration
`config.js` (copied into the image as `config/vnc-hybrid-authenticator.js`) is env-driven;
the `development` profile reads `NODE_ENV`-scoped values from `process.env` (LDAP URI/bind,
Postgres host/port/name/user/pass, `xmppToken`, `domain`). Provide them via the deployment
(ArgoCD in the `vnc-iac-env` GitOps repo), sourced from Infisical — do **not** commit
secrets to this repo.
## Deploy
Deployed by the ArgoCD application in `vnc-iac-env` (the hybrid-auth service that Prosody
and the mail/talk APIs call). This repo has no live deploy manifest; the image tag is pinned
in that GitOps repo.
## Legacy removed
The GitLab CI (`.gitlab-ci.yml`), `Jenkinsfile.deprecated`, and the GCP dev bootstrap
(`startgcpdevapi.sh`) were removed during the GitLab → Gitea migration. The old
`eu.gcr.io/vnc-development/vnc-hybridauth-api` promotion flow (`prod-*` / `stable-*` tags)
is not carried over; the current build pushes a single `master``sha-*` + `latest`.
+189 -38
View File
@@ -5,7 +5,7 @@ var jwt = require('jsonwebtoken');
var express = require('express');
require('express-async-errors');
var bodyParser = require('body-parser');
var request = require('request');
var request = require('@cypress/request');
var Pool = require('pg-pool');
var LDAP = require('ldapjs');
@@ -30,7 +30,8 @@ var base = config.ldap.searchBase; // default base for all future searches
//filter: config.ldap.filter, // default filter for all future searches
var scope = 'sub'; // scope: LDAP.SUBTREE
if (!config.useRedmineAuth) {
if (!config.noLDAP) {
if (!config.useRedmineAuth) {
ldap = LDAP.createClient({
url: config.ldap.ldapUri, // string
// do not wait longer than 1 minute for ldap connect
@@ -41,31 +42,64 @@ if (!config.useRedmineAuth) {
failAfter: 10
}
});
}
}
var dbpool = new Pool({
let dbpoolOpts = {
database: config.database.name,
user: config.database.user,
password: config.database.pass,
host: config.database.host,
port: config.database.port,
ssl: true,
max: 20, // set pool max size to 20
min: 4, // set min pool size to 4
idleTimeoutMillis: config.database.idleTimeoutMillis, // close idle clients after 1 second
connectionTimeoutMillis: config.database.connectionTimeoutMillis, // return an error after 1 second if connection could not be established
})
}
if (!config.disableDBtls) {
dbpoolOpts['ssl'] = { rejectUnauthorized: false };
}
var dbpool = new Pool(dbpoolOpts);
let projectPoolOpts = {
database: config.vncproject.name,
user: config.vncproject.user,
password: config.vncproject.pass,
host: config.vncproject.host,
port: config.vncproject.port,
max: 20, // set pool max size to 20
min: 4, // set min pool size to 4
idleTimeoutMillis: config.database.idleTimeoutMillis, // close idle clients after 1 second
connectionTimeoutMillis: config.database.connectionTimeoutMillis, // return an error after 1 second if connection could not be established
}
if (!config.disableDBtls) {
projectPoolOpts['ssl'] = { rejectUnauthorized: false };
}
var projectPool;
if (config.vncproject) {
projectPool = new Pool(projectPoolOpts);
}
app.use(bodyParser.json()); // for parsing application/json
app.use(logger('dev'));
function IsValidLDAPUser(username) {
return new Promise( function (resolve, reject) {
console.log("[IsValidLDAPUser start] username: ", username);
var uid = username.split("@")[0];
var domain = username.split("@")[1];
var domain = config.domain;
var email = username;
if (username.indexOf("@") > -1) {
domain = username.split("@")[1];
} else {
email = username + "@" + domain;
}
var dcstring = "ou=people,dc=";
if (domain.indexOf(".") > -1 ){
var dcstrings = domain.split(".");
@@ -73,6 +107,9 @@ function IsValidLDAPUser(username) {
dcstring += dcstrings.join(",dc=");
}
}
console.log("uid: ", uid);
console.log("domain: ", domain);
console.log("dc: ", dcstring);
if ((config.searchBase) && (config.searchBase != null)) {
dcstring = config.searchBase;
@@ -84,19 +121,19 @@ function IsValidLDAPUser(username) {
_filter += '(!(zimbraIsSystemResource=TRUE))(!(zimbraIsSystemAccount=TRUE))';
_filter += '(!(objectClass=zimbraDistributionList))(!(objectClass=zimbraCalendarResource))';
_filter += '(&(zimbraAccountStatus=active))(&(zimbraMailStatus=enabled))';
_filter += '(|(uid=' + uid + ')(mail=' + username + ')))';
_filter += '(|(uid=' + uid + ')(mail=' + email + ')))';
search_options.filter = _filter;
// search_options.attributes = ['uid', 'mail', 'givenName', 'sn', 'displayName', 'zimbraAccountStatus'];
search_options.attributes = ['uid', 'mail', 'zimbraAccountStatus'];
search_options.attributes = ['uid', 'mail', 'zimbraAccountStatus', 'givenName', 'sn', 'displayName', 'title', 'telephoneNumber', 'l', 'street', 'postalCode', 'co'];
} else if (config.ldap.ldapType === 'MS-AD') {
_filter = adBaseFilter;
_filter += '(|(sAMAccountName=' + uid + ')(mail=' + username + ')))';
search_options.filter = _filter;
search_options.attributes = ['sAMAccountName', 'mail', 'givenName', 's', 'displayName' ];
search_options.attributes = ['sAMAccountName', 'mail', 'givenName', 'sn', 'displayName' ];
} else {
console.error(moment().format("LTS") + " [profile ldap] unsupported config.ldap.ldapType : '"+config.ldap.ldapType+"'");
resolve(false);
resolve(null);
}
console.log(moment().format("LTS") + ' ldap filter: ', _filter);
ldap.bind(
@@ -105,14 +142,14 @@ function IsValidLDAPUser(username) {
err => {
if (err) {
console.error(moment().format("LTS") + " [profile ldap.bind]", err);
resolve(false);
resolve(null);
} else {
var resultEntries = [];
console.log(moment().format("LTS") + ' [profile ldap.search] dcstring:', dcstring);
ldap.search(dcstring, search_options, (error, searchResult) => {
if (error) {
console.error(moment().format("LTS") + " [profile ldap.search error] ", error);
resolve(false);
resolve(null);
}
searchResult.on('searchEntry' , e => {
var resultEntry = {};
@@ -129,13 +166,14 @@ function IsValidLDAPUser(username) {
{
console.log('[search-ldap.end] status=' + status.status + " ("+status.errorMessage+")", resultEntries.length+ " entries");
if (resultEntries.length === 1) {
console.log(moment().format("LTS") + " [valid LDAP user] resultEntries: ", resultEntries);
console.log(moment().format("LTS") + " [valid LDAP user] ", username);
ldap.unbind();
resolve(true);
resolve(resultEntries[0]);
} else {
console.log(moment().format("LTS") + " [no valid LDAP user] - sending 401");
ldap.unbind();
resolve(false);
resolve(null);
}
});
});
@@ -171,6 +209,7 @@ function IsValidLDAPAuth(username, password) {
console.error(moment().format("LTS") + " [profile ldap] unsupported config.ldap.ldapType : '"+config.ldap.ldapType+"'");
resolve(false);
}
console.log("LDAP Auth - UID DN: ", uiddn);
ldap.bind( uiddn, password,
err => {
if (err) {
@@ -186,18 +225,61 @@ function IsValidLDAPAuth(username, password) {
});
}
function getProjectApiKey(username) {
return new Promise( function (resolve, reject) {
var pqueryparams = [];
pqueryparams[0] = username;
pqueryparams[1] = "api";
pquery = "select tokens.value AS RedmineAPIKey from tokens where tokens.action=$2 and tokens.user_id in ";
pquery += "(select id from users where users.status=1 and id in (select user_id from email_addresses where address=$1))"
projectPool.query(pquery, pqueryparams, function (perr, pres) {
if (perr != null) {
console.log("db connection error: ", perr);
resolve(null);
} else {
if (pres.rowCount > 0) {
console.log("pres: ", pres.rows);
resolve(pres.rows[0].redmineapikey);
} else {
resolve(null);
}
}
})
});
}
function IsValidRedmineUser(username) {
return new Promise( function (resolve, reject) {
var uid = username.split("@")[0];
var query = ""
var queryparams = [];
queryparams[0] = uid;
var query = "SELECT DISTINCT ON (uid) users.login AS uid, users.firstname AS givenName, users.lastname AS sn FROM users WHERE users.status=1 AND lower(users.login)=$1";
queryparams[1] = "api";
queryparams[2] = "@" + config.domain;
query = "SELECT users.login AS uid, users.firstname AS givenName, users.lastname AS sn, organizations.name as memberOf, organizations.active as org_active, ";
query += " users.login||$3 as email, tokens.value AS RedmineAPIKey FROM users, tokens, organization_users, organizations ";
query += " WHERE users.status=1 AND lower(users.login)=$1 and tokens.action=$2 and tokens.user_id=users.id and organization_users.user_id=users.id and organizations.id=organization_users.organization_id and organizations.active";
// var query = "select SELECT DISTINCT ON (uid) users.login AS uid, users.firstname AS givenName, users.lastname AS sn, users.login||\'@talk.vnc.de\' AS mail FROM users WHERE users.status=1 AND users.login=$1 AND substring(users.hashed_password, 0, length(users.hashed_password)+1) = encode(digest(users.salt||encode(digest(:password, \'sha1\'), \'hex\'), \'sha1\'), \'hex\')";
dbpool.query(query, queryparams, function (derr, dres) {
if (derr == null) {
if (dres.rowCount > 0) {
resolve(true);
/*
console.log("isValidRedmine query: ", query);
console.log("isValidRedmine queryparams: ", queryparams);
console.log("isValidRedmine dres.rows: ", dres.rows);
*/
var redmineUser = {
id: dres.rows[0].uid,
firstname: dres.rows[0].givenname,
lastname: dres.rows[0].sn,
email: dres.rows[0].email,
displayName: dres.rows[0].givenname + " " + dres.rows[0].sn,
redmineapikey: dres.rows[0].redmineapikey
}
resolve(redmineUser);
} else {
resolve(false);
}
@@ -330,7 +412,6 @@ function IsValidOldSecret(username, password) {
function IsValidJWT(username,password) {
try {
var xmppToken = config.xmppToken;
console.log("decodePlain: ", jwt.decode(password));
var decodedToken = jwt.verify(password, xmppToken);
console.log("decodedJWT: ", decodedToken);
return true;
@@ -340,11 +421,21 @@ function IsValidJWT(username,password) {
}
}
function getFirstElement(elements) {
var result;
if (typeof(elements) == "string"){
result = elements;
} else if (typeof(elements) == "object") {
result = elements[0];
}
return result;
}
app.get('/', async function (req, res) {
if (req.headers.authorization && req.headers.authorization.startsWith("Basic")) {
try {
var b64input = req.headers.authorization.split(" ")[1];
var decodedInput = new Buffer(b64input, 'base64').toString('ascii');
var decodedInput = Buffer.from(b64input, 'base64').toString('ascii');
var username = decodedInput.split(":")[0];
var passwordArray = decodedInput.split(":");
var password = "";
@@ -355,22 +446,33 @@ app.get('/', async function (req, res) {
}
}
if (config.useRedmineAuth) {
let validRedmineUser = await IsValidRedmineUser(username);
console.log(moment().format("LTS") + ' username ' + username +' - IsValidRedmineUser: ', validRedmineUser);
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
let validRedmineUser = false;
var finalProfile = {};
let userProfile = await IsValidRedmineUser(username);
if (userProfile) {
validRedmineUser = true;
}
console.log(moment().format("LTS") + ' username ' + username +' - IsValidRedmineUser: ', validRedmineUser, userProfile);
if (config.debug) {
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
}
console.log(moment().format("LTS") + ' username ' + username +' - indesxforOldToken: ', password.indexOf("-"));
if (validRedmineUser === true) {
let validRedmineAuth = await IsValidRedmineAuth(username, password);
console.log("IsValidRedmineAuth: ", validRedmineAuth);
console.log("IsValidOldSecret: ", IsValidOldSecret(username, password));
if (config.debug) {
console.log("IsValidOldSecret: ", IsValidOldSecret(username, password));
}
console.log("IsValidJWT: ", IsValidJWT(username, password));
if (validRedmineUser && (validRedmineAuth || IsValidOldSecret(username, password) || IsValidJWT(username, password))) {
res.status(200).json(null);
res.set({"WWW-Authenticate": "Basic " + username}).status(200).json(userProfile);
} else {
res.status(401).json(null);
res.set({"WWW-Authenticate": "Basic " + username}).status(401).json(null);
}
} else {
res.status(401).json(null);
res.set({"WWW-Authenticate": "Basic " + username}).status(401).json(null);
}
} else {
@@ -382,15 +484,52 @@ app.get('/', async function (req, res) {
res.status(401).json(null);
}
} else {
let validLdapUser = await IsValidLDAPUser(username);
var finalProfile = {};
let userProfile = await IsValidLDAPUser(username);
let projectApiKey = await getProjectApiKey(username);
let validLdapUser = false;
let userLdapName = username;
console.log("got profile: ", userProfile);
if (userProfile) {
validLdapUser = true;
}
if (userProfile.uid && (userProfile.uid != null)) {
finalProfile["id"] = getFirstElement(userProfile.uid);
}
if (userProfile.givenName && (userProfile.givenName != null)) {
finalProfile["firstname"] = getFirstElement(userProfile.uid);
}
if (userProfile.sn && (userProfile.sn != null)) {
finalProfile["lastname"] = getFirstElement(userProfile.sn);
}
if (userProfile.email && (userProfile.email != null)) {
finalProfile["email"] = getFirstElement(userProfile.email);
userLdapName = getFirstElement(userProfile.email);
console.log("using for LDAP: ", userLdapName);
}
if (userProfile.mail && (userProfile.mail != null)) {
finalProfile["email"] = getFirstElement(userProfile.email);
userLdapName = getFirstElement(userProfile.mail);
console.log("using for LDAP: ", userLdapName);
}
if (userProfile.displayName && (userProfile.displayName != null)) {
finalProfile["displayName"] = getFirstElement(userProfile.displayName);
}
if (projectApiKey && (projectApiKey != null)) {
finalProfile["RedmineApiKey"] = projectApiKey;
}
console.log(moment().format("LTS") + ' username ' + username +' - validInLDAP: ', validLdapUser);
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
if (config.debug) {
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
}
console.log(moment().format("LTS") + ' username ' + username +' - indesxforOldToken: ', password.indexOf("-"));
if (validLdapUser === true) {
let validLdapAuth = await IsValidLDAPAuth(username, password);
// let validLdapAuth = await IsValidLDAPAuth(username, password);
let validLdapAuth = await IsValidLDAPAuth(userLdapName, password);
if (validLdapUser && (validLdapAuth || IsValidOldSecret(username, password) || IsValidJWT(username, password))) {
// if (IsValidOldSecret(username, password) || IsValidJWT(username, password)) {
res.status(200).json(null);
res.status(200).json(finalProfile);
} else {
res.status(401).json(null);
}
@@ -415,7 +554,7 @@ app.get('/login2fa', async function (req, res) {
if (req.headers.authorization && req.headers.authorization.startsWith("Basic")) {
try {
var b64input = req.headers.authorization.split(" ")[1];
var decodedInput = new Buffer(b64input, 'base64').toString('ascii');
var decodedInput = Buffer.from(b64input, 'base64').toString('ascii');
var username = decodedInput.split(":")[0];
var passwordArray = decodedInput.split(":");
var password = "";
@@ -434,17 +573,22 @@ app.get('/login2fa', async function (req, res) {
validRedmineUser = true;
}
console.log(moment().format("LTS") + ' username ' + username +' - IsValidRedmineUser: ', validRedmineUser);
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
console.log(moment().format("LTS") + ' username ' + username +' - userProfile: ', userProfile);
if (config.debug) {
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
}
console.log(moment().format("LTS") + ' username ' + username +' - indesxforOldToken: ', password.indexOf("-"));
if (validRedmineUser === true) {
let validRedmineAuth = await IsValidRedmineAuth(username, password);
console.log("IsValidRedmineAuth: ", validRedmineAuth);
console.log("IsValidOldSecret: ", IsValidOldSecret(username, password));
if (config.debug) {
console.log("IsValidOldSecret: ", IsValidOldSecret(username, password));
}
console.log("IsValidJWT: ", IsValidJWT(username, password));
if (validRedmineUser && (validRedmineAuth || IsValidOldSecret(username, password) || IsValidJWT(username, password))) {
res.status(200).json(userProfile);
res.set({"WWW-Authenticate": "Basic " + username}).status(200).json(userProfile);
} else {
res.status(401).json(null);
res.set({"WWW-Authenticate": "Basic " + username}).status(401).json(null);
}
} else {
res.status(401).json(null);
@@ -494,7 +638,9 @@ app.get('/login2fa', async function (req, res) {
finalProfile["RedmineApiKey"] = projectApiKey;
}
console.log(moment().format("LTS") + ' username ' + username +' - validInLDAP: ', validLdapUser);
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
if (config.debug) {
console.log(moment().format("LTS") + ' username ' + username +' - password: ', password);
}
console.log(moment().format("LTS") + ' username ' + username +' - indesxforOldToken: ', password.indexOf("-"));
if (validLdapUser === true) {
// let validLdapAuth = await IsValidLDAPAuth(username, password);
@@ -518,11 +664,16 @@ app.get('/login2fa', async function (req, res) {
}
} else {
console.log(moment().format("LTS") + ' no auth header');
res.status(401).json(null);
res.set({"WWW-Authenticate": "Basic vnclagoon"}).status(401).json(null);
}
});
app.get('/health', async function (req, res) {
console.log(moment().format("LTS") + ' health check called');
res.status(200).json(null);
});
var server = app.listen(servicePort, function () {
var host = server.address().address;
var port = server.address().port;
+60
View File
@@ -0,0 +1,60 @@
module.exports = {
development: {
servicePort: 9544,
disableDBtls: process.env.disableDBtls || false,
domain: process.env.domain || 'dev.vnc.de',
xmppToken: process.env.xmppToken || 'xah6niighohshieKahtah',
useRedmineAuth: true,
ldap: {
ldapUri: process.env.ldapUri || 'none',
bindDn: process.env.bindDn || 'uid=zimbra,cn=admins,cn=zimbra',
bindPassword: process.env.bindPassword || 'none',
searchBase: process.env.searchBase || 'none',
filter: process.env.filter || '(objectClass=inetOrgPerson)',
config: 100,
// valid ldapType for now: MS-AD, zimbra
ldapType: process.env.ldapType || 'zimbra'
},
database: {
host: process.env.databaseHost || "127.0.0.1",
port: process.env.databasePort || 54322,
name: process.env.databaseName || "redmine",
user: process.env.databaseUser || "redmine",
pass: process.env.databasePass || "redmine",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
},
vncproject: {
host: process.env.redmineDbHost || "127.0.0.1",
port: process.env.redmineDbPort || 54322,
name: process.env.redmineDbName || "redmine",
user: process.env.redmineDbUser || "redmine",
pass: process.env.redmineDbPass || "redmine",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
}
},
gr13: {
servicePort: 9544,
xmppToken: process.env.xmppToken || 'ocu8saithoYa2teeb2ahTh9fee4is7ai',
ldap: {
ldapUri: process.env.ldapUri || 'ldap://192.168.21.142:389',
bindDn: process.env.bindDn || 'uid=zimbra,cn=admins,cn=zimbra',
bindPassword: process.env.bindPassword || 'jSVNIcRSRR',
searchBase: process.env.searchBase || 'ou=people,dc=dev,dc=local,dc=gr13,dc=net',
filter: process.env.filter || '(objectClass=inetOrgPerson)',
config: 100,
// valid ldapType for now: MS-AD, zimbra
ldapType: process.env.ldapType || 'zimbra'
},
database : {
host: process.env.prosodyDbHost || "192.168.21.143",
port: process.env.prosodyDbPort || 5432,
name: process.env.prosodyDbName || "prosody",
user: process.env.prosodyDbUser || "prosody",
pass: process.env.prosodyDbPass || "vahG7ooli7thee0iek4Ewoo9Sai6oWah",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
}
},
};
+18 -39
View File
@@ -1,63 +1,42 @@
module.exports = {
development: {
servicePort: 9544,
domain: 'vncmeet.com',
xmppToken: 'oothoudaeraighahkabahphisaiwaeko',
domain: 'dev.vnc.de',
xmppToken: 'xah6niighohshieKahtah',
useRedmineAuth: true,
disableDBtls: false,
ldap: {
ldapUri: 'ldap://zimbra.uxf.zimbra-vnc.de:389',
ldapUri: 'none',
bindDn: 'uid=zimbra,cn=admins,cn=zimbra',
bindPassword: 'cfQ9f0KNR',
searchBase: 'ou=people,dc=uxf,dc=zimbra-vnc,dc=de',
bindPassword: 'none',
searchBase: 'none',
filter: '(objectClass=inetOrgPerson)',
config: 100,
// valid ldapType for now: MS-AD, zimbra
ldapType: 'zimbra'
},
database: {
host: "talk.uxf.zimbra-vnc.de",
port: 5432,
name: "prosody",
user: "prosody",
pass: "oolehohqueithaipeikahtaeshoozais",
host: "127.0.0.1",
port: 54322,
name: "redmine",
user: "redmine",
pass: "redmine",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
},
redminedb: {
host: "talk.uxf.zimbra-vnc.de",
port: 5432,
name: "prosody",
user: "prosody",
pass: "oolehohqueithaipeikahtaeshoozais",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
}
},
development2: {
xmppToken: 'irithep1KeiViemohmui3fo3eiyeitah',
servicePort: 9544,
ldap: {
ldapUri: 'ldap://193.254.187.146:389',
bindDn: 'uid=zimbra,cn=admins,cn=zimbra',
bindPassword: 'tTBhTIWS',
searchBase: 'ou=people,dc=dev2,dc=zimbra-vnc,dc=de',
filter: '(objectClass=inetOrgPerson)',
config: 100,
// valid ldapType for now: MS-AD, zimbra
ldapType: 'zimbra'
},
database: {
host: "193.254.187.146",
port: 5432,
name: "prosody",
user: "prosody",
pass: "ooX8ieyu9uaGee6aechukoh1beePaiZoo",
host: "127.0.0.1",
port: 54322,
name: "redmine",
user: "redmine",
pass: "redmine",
idleTimeoutMillis: 10000,
connectionTimeoutMillis: 10000
}
},
gr13: {
servicePort: 9544,
xmppToken: 'ocu8saithoYa2teeb2ahTh9fee4is7ai',
xmppToken: 'ocu8saithoYa2teeb2ahTh9fee4is7ai',
ldap: {
ldapUri: 'ldap://192.168.21.142:389',
bindDn: 'uid=zimbra,cn=admins,cn=zimbra',
+20 -12
View File
@@ -5,24 +5,32 @@
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=development node app/app.js",
"start": "node app/app.js",
"start:gr13": "NODE_ENV=gr13 node app/app.js"
},
"author": "VNC Software AG",
"license": "",
"dependencies": {
"body-parser": "1.18.3",
"express": "4.13.4",
"body-parser": "1.20.3",
"express": "4.22.1",
"express-async-errors": "3.1.1",
"express-basic-auth": "1.1.6",
"express-basic-auth": "1.2.1",
"hmacsha1": "1.0.0",
"jsonwebtoken": "8.3.0",
"ldapjs": "^1.0.2",
"md5": "2.2.1",
"moment": "2.22.2",
"morgan": "1.8.2",
"pg": "7.6.0",
"pg-pool": "2.0.3",
"request": "2.83.0"
"jsonwebtoken": "9.0.3",
"ldapjs": "1.0.2",
"md5": "2.3.0",
"moment": "2.29.4",
"morgan": "1.10.1",
"pg": "8.8.0",
"pg-pool": "3.5.2",
"@cypress/request": "3.0.10"
},
"resolutions": {
"brace-expansion": "5.0.6",
"form-data": "4.0.6",
"lodash": "4.18.1",
"minimatch": "10.2.4",
"qs": "6.15.2",
"uuid": "14.0.0"
}
}
View File
+5
View File
@@ -0,0 +1,5 @@
BROADCASTSENDER=jenkins.bot@vnc.biz
BROADCASTID=broadcast-gel4it1o9fvi@vnc.biz
BCTITLE=Factory - VNC Hybridauth2
BCRECEIPIENTS=leonidas.apostolidis@vnc.biz
BCRESTURL=https://xmpp.vnc.biz/rest
+77
View File
@@ -0,0 +1,77 @@
#!/bin/bash
#######
# Use Jenkins env vars if set otherwise use the gitlab-ci ones
BUILD_URL=${BUILD_URL:-$CI_PIPELINE_URL}
BRANCH_NAME=${BRANCH_NAME:-$CI_COMMIT_REF_NAME}
#######
echo "BRANCH: $BRANCH_NAME"
if [ -f result.txt ]; then
RESULT=$(cat result.txt)
#debug
echo "result:"
cat result.txt
fi
if [ -f code-analysis.txt ]; then
CODEERR=$(cat code-analysis.txt)
#debug
echo "code-analysis"
cat code-analysis.txt
fi
AUTHOR=$(git log -1 | grep "^Author: " | awk -F "Author:" '{print $2}' | awk -F "<" '{print $1}')
echo "All local branches:"; git branch
echo "BRANCH_NAME: $BRANCH_NAME"
JCHANGELOG=$(git log --pretty=format:%s origin/master..origin/$BRANCH_NAME | nl)
echo "changes:"
echo "$JCHANGELOG"
if [ "$RESULT" ]; then
echo "$BUILD_URL - $RESULT"
case $RESULT in
SUCCESS|success)
if [ "$BRANCH_NAME" = "master" ]; then
echo -e "job succesfully finished: $BUILD_URL \n Changes: \n $JCHANGELOG" | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job succesfully finished: $BUILD_URL - new APK is available at https://basepackages.vnc.biz/apk/VNCmail-2.0.0-$BUILD_ID.apk"
else
echo -e "job succesfully finished: $BUILD_URL \n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job succesfully finished: $BUILD_URL"
fi
;;
UNSTABLE|WARNING|unstable)
if [ "$CODEERR" ]; then
if [ "$BRANCH_NAME" = "master" ]; then
echo -e "job finished with warnings: $BUILD_URL \n $CODEERR \n Changes: \n $JCHANGELOG " | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job finished with warnings: $BUILD_URL \n $CODEERR \n new APK is available at https://basepackages.vnc.biz/apk/VNCmail-2.0.0-$BUILD_ID.apk"
else
echo -e "job finished with warnings: $BUILD_URL \n $CODEERR \n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job finished with warnings: $BUILD_URL \n $CODEERR"
fi
else
echo -e "job finished with warnings: $BUILD_URL \n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
#nagzillac "room^vncmail__project@conference.vnc.biz^job finished with warnings: $BUILD_URL"
fi
;;
FAILURE)
if [ "$CODEERR" ]; then
CODENUM=$(wc -l code-analysis.txt | awk '{print $1}')
echo -e "job FAILED - please check: $BUILD_URL \n code analysis found $CODENUM errors \n $CODEERR \n\n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job FAILED - please check: $BUILD_URL \n code analysis found $CODENUM errors"
else
echo -e "job FAILED - please check: $BUILD_URL immediately \n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
# nagzillac "room^vncmail__project@conference.vnc.biz^job FAILED - please check: $BUILD_URL immediately"
fi
;;
*)
echo -e "job finished with ambigous result - please check: $BUILD_URL immediately \n Changes: \n $JCHANGELOG \n Author: $AUTHOR" | ./tools/sendbroadcast.sh
# nagzillac "chat^stefan.saenger@vnc.biz^job finished with ambigous result - please check: $BUILD_URL immediately"
;;
esac
fi
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
BCBODY=`cat`
function die_err() {
echo "$0: $*" >&2
exit 1
}
OldPWD=$(pwd)
BaseDir=$(git rev-parse --show-toplevel)
cd "$BaseDir" || exit 1
CURLCRED="vnctalk:ohtai2Eicai4aiting7bec2am6Aih"
if [ -f "tools/broadcast.cfg" ]; then
echo "found config"
else
cd "$OldPWD" || exit 1
die_err "no broadcst config - bailing out"
fi
RECEIPIENTS=$(cat tools/broadcast.cfg | grep "^BCRECEIPIENTS" | awk -F "=" '{print $2}' | tr ',' '\n' | awk '{print "<to>" $0 "</to>"}' | sed 's/ //g' | grep -v "<to></to>");
BROADCASTSENDER=$(cat tools/broadcast.cfg | grep "^BROADCASTSENDER" | awk -F "=" '{print $2}');
BROADCASTID=$(cat tools/broadcast.cfg | grep "^BROADCASTID" | awk -F "=" '{print $2}');
BCTITLE=$(cat tools/broadcast.cfg | grep "^BCTITLE" | awk -F "=" '{print $2}');
MSGID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
BCRESTURL=$(cat tools/broadcast.cfg | grep "^BCRESTURL" | awk -F "=" '{print $2}');
echo "<message xmlns=\"jabber:client\" type=\"normal\" id=\"$MSGID\" to=\"$BROADCASTID\" from=\"$BROADCASTSENDER\">" > "/tmp/$MSGID.xml"
echo "<body>$BCBODY</body>" >> "/tmp/$MSGID.xml"
echo "<vncTalkBroadcast xmlns=\"xmpp:vnctalk\" title=\"$BCTITLE\">" >> "/tmp/$MSGID.xml"
echo "$RECEIPIENTS" >> "/tmp/$MSGID.xml"
echo " </vncTalkBroadcast>
</message>" >> "/tmp/$MSGID.xml"
echo "raw message:"
cat "/tmp/$MSGID.xml"
curl -u "$CURLCRED" -H "Content-Type: text/xml" -X POST --data-binary "@/tmp/$MSGID.xml" "$BCRESTURL"
+760 -649
View File
File diff suppressed because it is too large Load Diff