Skip to content

Commit

Permalink
Merge pull request #214 from eurofurence/issue-213-docker-build
Browse files Browse the repository at this point in the history
feat(#213): add latest container build
  • Loading branch information
Jumpy-Squirrel committed Dec 7, 2023
2 parents f4042ec + a440c7a commit 021e2b1
Show file tree
Hide file tree
Showing 18 changed files with 322 additions and 26 deletions.
58 changes: 58 additions & 0 deletions .github/workflows/docker-build-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Create and publish Docker image

on:
push:
branches:
- 'main'

jobs:
build-and-push-image:
permissions:
contents: read
packages: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions/setup-node@v3
with:
node-version: '18'
registry-url: 'https://npm.pkg.github.com'
scope: '@eurofurence'

- run: npm install
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- run: npm run build -- --no-uglify
shell: bash
env:
PATH_PREFIX: '/aN3nNFwFoi5QkyPaVJ54dDTDc6HrrCYGAL6U6GUuyV2uvvekgOxqYe6K2hur/app'
GATSBY_API_BASE_URL: '/aN3nNFwFoi5QkyPaVJ54dDTDc6HrrCYGAL6U6GUuyV2uvvekgOxqYe6K2hur'
PREFIX_PATHS: 'true'

- name: Log in to the Container registry
run: 'echo "$REGISTRY_PASS" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin'
shell: bash
env:
REGISTRY: 'ghcr.io'
REGISTRY_USER: ${{ github.actor }}
REGISTRY_PASS: ${{ secrets.GITHUB_TOKEN }}

- name: Docker build and push image
run: >
TAG_ARGS=$(echo -n "$IMAGE_TAGS" | sed -r "s_([^ :/]+)_ --tag $REGISTRY/$IMAGE_NAME:\1 _g") &&
docker build
--label org.opencontainers.image.url="$FULL_REPO_URL"
--label org.opencontainers.image.revision="$COMMIT_HASH"
$TAG_ARGS
--pull
. &&
docker push -a "$REGISTRY/$IMAGE_NAME"
shell: bash
env:
REGISTRY: 'ghcr.io'
IMAGE_NAME: ${{ github.repository }}
IMAGE_TAGS: latest
FULL_REPO_URL: "https://github.com/${{ github.repository }}"
COMMIT_HASH: ${{ github.sha }}
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM alpine:3

RUN apk add --no-cache apache2 apache2-http2 apache2-proxy \
&& rm -rf /usr/sbin/fcgistarter /usr/sbin/suexec /var/www \
&& mkdir -p /static-html/htdocs

COPY ./httpd-container.conf /etc/apache2/regsys.conf
COPY ./public /static-html/regsys/app

# TODO set up minimal base website under /static-html/
# (favicon, 404.html, blank white page index.html, ...)

RUN chmod -R go=rX /static-html /etc/apache2/regsys.conf

RUN find /static-html

EXPOSE 8080

USER 8877

CMD ["/usr/sbin/httpd", "-f", "/etc/apache2/regsys.conf"]
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ gatsby telemetry --disable
npm install
```

_Note: running node/npm from snaps may not work. Some problem with user detection when installing sharp, where it tries
to install as the wrong user and then runs into permission errors._

#### set up a local dotenv

```
Expand Down
132 changes: 132 additions & 0 deletions httpd-container.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
ServerTokens OS
ServerRoot /static-html
Listen 8080

LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule substitute_module modules/mod_substitute.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule dir_module modules/mod_dir.so
# LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so

LoadModule negotiation_module modules/mod_negotiation.so

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_http2_module modules/mod_proxy_http2.so

ServerAdmin ${HTTPD_CONF_SERVER_ADMIN_EMAIL}
ServerSignature Off

<Directory />
AllowOverride none
Require all denied
</Directory>

DocumentRoot "/static-html/htdocs"

<Directory "/var/www/localhost/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>

<IfModule dir_module>
DirectoryIndex index.html
</IfModule>

<Files ".ht*">
Require all denied
</Files>

ErrorLog /dev/stdout
CustomLog /dev/stdout combined
LogLevel warn

<IfModule mime_module>
TypesConfig /etc/apache2/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
</IfModule>

<VirtualHost *:8080>
ServerName ${HTTPD_CONF_SERVER_NAME}
ServerAdmin ${HTTPD_CONF_SERVER_ADMIN_EMAIL}
DocumentRoot /static-html/reg-frontend

Header always set Content-Security-Policy "default-src 'self' 'unsafe-inline'; img-src 'self' data: ; font-src 'self' data: ;"

<Directory /static-html/reg-frontend/>
Require all granted
Options FollowSymLinks MultiViews
</Directory>

# This is a security measure in the event that our Api Key ever leaks
RequestHeader unset X-Api-Key

# This is a temporary security measure until 2FA arrives
RequestHeader unset X-Admin-Request

ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/regsys http://reg-regsys-classic:8080
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/regsys http://reg-regsys-classic:8080

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/attsrv/ http://reg-attendee-service:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/attsrv/ http://reg-attendee-service:8080/

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/roomsrv/ http://reg-room-service:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/roomsrv/ http://reg-room-service:8080/

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/authsrv/ http://reg-auth-service:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/authsrv/ http://reg-auth-service:8080/

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/paysrv/ http://reg-payment-service:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/paysrv/ http://reg-payment-service:8080/

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/cncrdsrv/ http://reg-payment-cncrd-adapter:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/cncrdsrv/ http://reg-payment-cncrd-adapter:8080/

# ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/expsrv/ http://reg-export-service:8080/
# ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/expsrv/ http://reg-export-service:8080/

ProxyPass /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/mailsrv/ http://reg-mail-service:8080/
ProxyPassReverse /${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/mailsrv/ http://reg-mail-service:8080/

# configuration for reg-frontend

RewriteEngine on
RewriteRule "^/${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/app/register/[a-z-]+/.*$" "/${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}/app/register/index.html"

# we have built the gatsby static app with this context base path, so we use inline content substitution
Substitute "s|aN3nNFwFoi5QkyPaVJ54dDTDc6HrrCYGAL6U6GUuyV2uvvekgOxqYe6K2hur|${HTTPD_CONF_PATH_PREFIX_NO_SLASHES}|n"

ErrorLog /dev/stdout
CustomLog /dev/stdout combined
LogLevel warn
ServerSignature Off

ErrorDocument 404 /404.html
</VirtualHost>
36 changes: 27 additions & 9 deletions src/apis/attsrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ export interface AttendeeStatusDto {
readonly status: RegistrationStatus
}

/* eslint-disable @typescript-eslint/no-magic-numbers */
enum Weekdays {
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
}
/* eslint-enable @typescript-eslint/no-magic-numbers */

const tshirtFromApi = (apiValue: string | null) => {
if (apiValue === '3XL') {
return 'm3XL'
Expand Down Expand Up @@ -165,10 +177,13 @@ const attendeeDtoFromRegistrationInfo = (registrationInfo: RegistrationInfo): At
...flagsToOptions(registrationInfo.originalPackages ?? ''),
'room-none': true,
'attendance': registrationInfo.ticketType.type === 'full',
'day-sun': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === 7,
'day-mon': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === 1,
'day-tue': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === 2,
'day-wed': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === 3,
// 'day-mon': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Monday,
// 'day-tue': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Tuesday,
'day-wed': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Wednesday,
'day-thu': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Thursday,
'day-fri': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Friday,
'day-sat': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Saturday,
// 'day-sun': registrationInfo.ticketType.type === 'day' && registrationInfo.ticketType.day.weekday === Weekdays.Sunday,
'sponsor': registrationInfo.ticketLevel.level === 'sponsor',
'sponsor2': registrationInfo.ticketLevel.level === 'super-sponsor',
'stage': !(config.ticketLevels[registrationInfo.ticketLevel.level].includes?.includes('stage-pass') ?? false)
Expand All @@ -195,11 +210,14 @@ const registrationInfoFromAttendeeDto = (attendeeDto: AttendeeDto): Registration
? { type: 'full' }
: {
type: 'day',
day: packages.has('day-sun') ? days.find(d => d.weekday === 7)!
: packages.has('day-mon') ? days.find(d => d.weekday === 1)!
: packages.has('day-tue') ? days.find(d => d.weekday === 2)!
: packages.has('day-wed') ? days.find(d => d.weekday === 3)!
: days.find(d => d.weekday === 3)!, // FIXME: Cough
day: packages.has('day-sun') ? days.find(d => d.weekday === Weekdays.Sunday)!
: packages.has('day-mon') ? days.find(d => d.weekday === Weekdays.Monday)!
: packages.has('day-tue') ? days.find(d => d.weekday === Weekdays.Tuesday)!
: packages.has('day-wed') ? days.find(d => d.weekday === Weekdays.Wednesday)!
: packages.has('day-thu') ? days.find(d => d.weekday === Weekdays.Thursday)!
: packages.has('day-fri') ? days.find(d => d.weekday === Weekdays.Friday)!
: packages.has('day-sat') ? days.find(d => d.weekday === Weekdays.Saturday)!
: days.find(d => d.weekday === Weekdays.Wednesday)!, // better than nothing
},
/* eslint-enable @typescript-eslint/indent */
ticketLevel: {
Expand Down
2 changes: 1 addition & 1 deletion src/apis/authsrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface UserInfoDto {
readonly subject: string
readonly name: string
readonly email: string
readonly email_verified: boolean // TODO show message "you need to verify your email address before you can register with it"
readonly email_verified: boolean
readonly groups: readonly string[]
}

Expand Down
22 changes: 22 additions & 0 deletions src/apis/paysrv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,25 @@ export const initiateCreditCardPaymentOrUseExisting = (badgeNumber: number) =>
: initiateCreditCardPayment(badgeNumber)
}),
)

export const initiateSepaPayment = (badgeNumber: number) => apiCall<InitiatePaymentResponseDto>({
path: '/transactions/initiate-payment',
method: 'POST',
body: {
debitor_id: badgeNumber,
method: 'transfer',
},
}).pipe(
map(result => result.response.transaction),
)

export const initiateSepaPaymentOrUseExisting = (badgeNumber: number) =>
findTransactionsForBadgeNumber(badgeNumber).pipe(
concatMap(transactions => {
const tentativeTransaction = transactions.find(t => t.transaction_type === 'payment' && t.method === 'transfer' && t.status === 'tentative')

return tentativeTransaction !== undefined
? of(tentativeTransaction)
: initiateSepaPayment(badgeNumber)
}),
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { Localized } from '@fluent/react'
import WithInvoiceFunnelLayout from '~/components/funnels/layout/with-invoice'
import { useAppDispatch, useAppSelector } from '~/hooks/redux'
import { InitiatePayment } from '~/state/actions/register'
import { InitiatePayment, InitiateSepaPayment } from '~/state/actions/register'
import { buildInvoice } from '~/state/models/invoice'
import { getInvoice, getStatus, hasUnprocessedPayments, isEditMode } from '~/state/selectors/register'
import type { ReadonlyReactNode } from '~/util/readonly-types'
Expand Down Expand Up @@ -37,6 +37,7 @@ const WithInvoiceRegisterFunnelLayout = ({ children, currentStep, onNext }: With
hideInvoice={status === 'cancelled'}
unprocessedPayments={unprocessedPayments}
onPay={() => dispatch(InitiatePayment.create(undefined))}
onSepa={() => dispatch(InitiateSepaPayment.create(undefined))}
>
{children}
</WithInvoiceFunnelLayout>
Expand Down
4 changes: 2 additions & 2 deletions src/components/funnels/funnels/register/steps/summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ const Summary = (_: ReadonlyRouteComponentProps) => {
<StatusText status={status}>We have received your registration and will confirm it when things are ready. Keep an eye on your mailbox!</StatusText>
</Localized>

<Localized id="register-summary-registration-id" vars={{ registrationId }}>
{ registrationId ? <Localized id="register-summary-registration-id" vars={{ registrationId }}>
<RegistrationId>Badge number: {registrationId}</RegistrationId>
</Localized>
</Localized> : undefined }

<Section id="personal" editLink="/register/personal-info" properties={[
{ id: 'nickname', value: personalInfo.nickname },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface TicketLevelAddonProps {
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
const TicketLevelAddon = ({ addon, formContext }: TicketLevelAddonProps) => {
const isIncluded = (lvl: TicketLevel['level'] | null) => lvl !== null && (config.ticketLevels[lvl].includes?.includes(addon.id) ?? false)
const isRequired = (lvl: TicketLevel['level'] | null) => lvl !== null && (config.ticketLevels[lvl].requires?.includes(addon.id) ?? false)

const { watch, register, setValue } = formContext
const level = watch('level')
Expand All @@ -39,7 +40,7 @@ const TicketLevelAddon = ({ addon, formContext }: TicketLevelAddonProps) => {
label={addon.id}
description={addon.id}
price={isIncluded(level) ? 0 : addon.price}
disabled={isIncluded(level)}
disabled={isIncluded(level) || isRequired(level)}
{...register(`addons.${addon.id}.selected`)}
>
{Object.entries(addon.options).map(([id, option]) =>
Expand Down
Loading

0 comments on commit 021e2b1

Please sign in to comment.