feat: Lock webchat to irc.supernets.org with simplified connect form
This commit configures Hard Lounge as a dedicated webchat client for SuperNETs IRC, requiring only a nickname to connect. - Set `public: true` to enable public mode (no user accounts required) - Set `lockNetwork: true` to lock connections to irc.supernets.org only Users will automatically connect to irc.supernets.org:6697 (TLS) and join #superbowl upon entering a nickname. - Added simplified connect form for public + lockNetwork mode - Form now shows only the nickname field when both settings are enabled - Hidden fields: server, port, TLS, username, realname, channels, leave message, authentication options - Added CSS styling for proper spacing on simplified form - Pinned to Node 20 Alpine (from lts-alpine) for compatibility - Added py3-setuptools to fix distutils module error with Python 3.12 - Fixed file ownership with --chown=node:node on COPY commands - Moved USER node directive after COPY to fix permission issues - Pre-create /var/opt/hardlounge directory with correct ownership
This commit is contained in:
14
Dockerfile
14
Dockerfile
@@ -1,18 +1,20 @@
|
||||
FROM node:lts-alpine
|
||||
RUN apk add --no-cache --virtual=build-dependencies build-base git python3-dev && \
|
||||
FROM node:20-alpine
|
||||
RUN apk add --no-cache --virtual=build-dependencies build-base git python3-dev py3-setuptools && \
|
||||
apk add --no-cache yarn
|
||||
USER node
|
||||
WORKDIR /var/opt/hardlounge-src
|
||||
ENV THELOUNGE_HOME /var/opt/hardlounge
|
||||
COPY package.json yarn.lock .
|
||||
COPY --chown=node:node package.json yarn.lock .
|
||||
USER node
|
||||
RUN yarn install
|
||||
COPY . .
|
||||
COPY --chown=node:node . .
|
||||
RUN NODE_ENV=production yarn build && \
|
||||
yarn link && \
|
||||
yarn --non-interactive cache clean && \
|
||||
ln -s /var/opt/hardlounge-src/index.js /var/opt/hardlounge-src/hardlounge
|
||||
USER root
|
||||
RUN apk del --purge build-dependencies
|
||||
RUN apk del --purge build-dependencies && \
|
||||
mkdir -p /var/opt/hardlounge && \
|
||||
chown -R node:node /var/opt/hardlounge
|
||||
USER node
|
||||
EXPOSE 9000
|
||||
CMD ["/var/opt/hardlounge-src/hardlounge", "start"]
|
||||
@@ -206,122 +206,143 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<h2>User preferences</h2>
|
||||
<div class="connect-row">
|
||||
<label for="connect:nick">Nick</label>
|
||||
<input
|
||||
id="connect:nick"
|
||||
v-model="defaults.nick"
|
||||
class="input nick"
|
||||
name="nick"
|
||||
pattern="[^\s:!@]+"
|
||||
maxlength="100"
|
||||
required
|
||||
@input="onNickChanged"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="!config?.useHexIp">
|
||||
<div class="connect-row">
|
||||
<label for="connect:username">Username</label>
|
||||
<!-- Simplified form for public + lockNetwork mode: only show nick -->
|
||||
<template v-if="config?.lockNetwork && store.state.serverConfiguration?.public">
|
||||
<div class="connect-row simple-nick">
|
||||
<label for="connect:nick">Nick</label>
|
||||
<input
|
||||
id="connect:username"
|
||||
ref="usernameInput"
|
||||
v-model.trim="defaults.username"
|
||||
class="input username"
|
||||
name="username"
|
||||
id="connect:nick"
|
||||
v-model="defaults.nick"
|
||||
class="input nick"
|
||||
name="nick"
|
||||
pattern="[^\s:!@]+"
|
||||
maxlength="100"
|
||||
required
|
||||
@input="onNickChanged"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div class="connect-row">
|
||||
<label for="connect:realname">Real name</label>
|
||||
<input
|
||||
id="connect:realname"
|
||||
v-model.trim="defaults.realname"
|
||||
class="input"
|
||||
name="realname"
|
||||
maxlength="300"
|
||||
/>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label for="connect:leaveMessage">Leave message</label>
|
||||
<input
|
||||
id="connect:leaveMessage"
|
||||
v-model.trim="defaults.leaveMessage"
|
||||
autocomplete="off"
|
||||
class="input"
|
||||
name="leaveMessage"
|
||||
placeholder="Hard Lounge - https://git.supernets.org/supernets/hardlounge"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="defaults.uuid && !store.state.serverConfiguration?.public">
|
||||
<!-- Full form for other modes -->
|
||||
<template v-else>
|
||||
<h2>User preferences</h2>
|
||||
<div class="connect-row">
|
||||
<label for="connect:commands">
|
||||
Commands
|
||||
<span
|
||||
class="tooltipped tooltipped-ne tooltipped-no-delay"
|
||||
aria-label="One /command per line.
|
||||
Each command will be executed in
|
||||
the server tab on new connection"
|
||||
>
|
||||
<button class="extra-help" />
|
||||
</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="connect:commands"
|
||||
ref="commandsInput"
|
||||
autocomplete="off"
|
||||
:value="defaults.commands ? defaults.commands.join('\n') : ''"
|
||||
class="input"
|
||||
name="commands"
|
||||
@input="resizeCommandsInput"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="!defaults.uuid">
|
||||
<div class="connect-row">
|
||||
<label for="connect:channels">Channels</label>
|
||||
<label for="connect:nick">Nick</label>
|
||||
<input
|
||||
id="connect:channels"
|
||||
v-model.trim="defaults.join"
|
||||
class="input"
|
||||
name="join"
|
||||
id="connect:nick"
|
||||
v-model="defaults.nick"
|
||||
class="input nick"
|
||||
name="nick"
|
||||
pattern="[^\s:!@]+"
|
||||
maxlength="100"
|
||||
required
|
||||
@input="onNickChanged"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="store.state.serverConfiguration?.public">
|
||||
<template v-if="config?.lockNetwork">
|
||||
<template v-if="!config?.useHexIp">
|
||||
<div class="connect-row">
|
||||
<label></label>
|
||||
<div class="input-wrap">
|
||||
<label class="tls">
|
||||
<input v-model="displayPasswordField" type="checkbox" />
|
||||
I have a password
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="displayPasswordField" class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword
|
||||
v-slot:default="slotProps"
|
||||
class="input-wrap password-container"
|
||||
>
|
||||
<input
|
||||
id="connect:password"
|
||||
ref="publicPassword"
|
||||
v-model="defaults.password"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
placeholder="Server password (optional)"
|
||||
name="password"
|
||||
maxlength="300"
|
||||
/>
|
||||
</RevealPassword>
|
||||
<label for="connect:username">Username</label>
|
||||
<input
|
||||
id="connect:username"
|
||||
ref="usernameInput"
|
||||
v-model.trim="defaults.username"
|
||||
class="input username"
|
||||
name="username"
|
||||
maxlength="100"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div class="connect-row">
|
||||
<label for="connect:realname">Real name</label>
|
||||
<input
|
||||
id="connect:realname"
|
||||
v-model.trim="defaults.realname"
|
||||
class="input"
|
||||
name="realname"
|
||||
maxlength="300"
|
||||
/>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label for="connect:leaveMessage">Leave message</label>
|
||||
<input
|
||||
id="connect:leaveMessage"
|
||||
v-model.trim="defaults.leaveMessage"
|
||||
autocomplete="off"
|
||||
class="input"
|
||||
name="leaveMessage"
|
||||
placeholder="Hard Lounge - https://git.supernets.org/supernets/hardlounge"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="defaults.uuid && !store.state.serverConfiguration?.public">
|
||||
<div class="connect-row">
|
||||
<label for="connect:commands">
|
||||
Commands
|
||||
<span
|
||||
class="tooltipped tooltipped-ne tooltipped-no-delay"
|
||||
aria-label="One /command per line.
|
||||
Each command will be executed in
|
||||
the server tab on new connection"
|
||||
>
|
||||
<button class="extra-help" />
|
||||
</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="connect:commands"
|
||||
ref="commandsInput"
|
||||
autocomplete="off"
|
||||
:value="defaults.commands ? defaults.commands.join('\n') : ''"
|
||||
class="input"
|
||||
name="commands"
|
||||
@input="resizeCommandsInput"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="!defaults.uuid">
|
||||
<div class="connect-row">
|
||||
<label for="connect:channels">Channels</label>
|
||||
<input
|
||||
id="connect:channels"
|
||||
v-model.trim="defaults.join"
|
||||
class="input"
|
||||
name="join"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="store.state.serverConfiguration?.public">
|
||||
<template v-if="config?.lockNetwork">
|
||||
<div class="connect-row">
|
||||
<label></label>
|
||||
<div class="input-wrap">
|
||||
<label class="tls">
|
||||
<input v-model="displayPasswordField" type="checkbox" />
|
||||
I have a password
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="displayPasswordField" class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword
|
||||
v-slot:default="slotProps"
|
||||
class="input-wrap password-container"
|
||||
>
|
||||
<input
|
||||
id="connect:password"
|
||||
ref="publicPassword"
|
||||
v-model="defaults.password"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
placeholder="Server password (optional)"
|
||||
name="password"
|
||||
maxlength="300"
|
||||
/>
|
||||
</RevealPassword>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
<!-- Authentication section only for private mode -->
|
||||
<template v-if="!store.state.serverConfiguration?.public && !(config?.lockNetwork && store.state.serverConfiguration?.public)">
|
||||
<h2 id="label-auth">Authentication</h2>
|
||||
<div class="connect-row connect-auth" role="group" aria-labelledby="label-auth">
|
||||
<label class="opt">
|
||||
@@ -435,6 +456,15 @@ the server tab on new connection"
|
||||
margin: 0;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
/* Simplified connect form styling */
|
||||
#connect .connect-row.simple-nick {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#connect .connect-row.simple-nick label {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = {
|
||||
// channels and scrollbacks are available when they come back.
|
||||
//
|
||||
// This value is set to `false` by default.
|
||||
public: false,
|
||||
public: true,
|
||||
|
||||
// ### `host`
|
||||
//
|
||||
@@ -287,7 +287,7 @@ module.exports = {
|
||||
// These fields will also be hidden from the UI.
|
||||
//
|
||||
// This value is set to `false` by default.
|
||||
lockNetwork: false,
|
||||
lockNetwork: true,
|
||||
|
||||
// ## User management
|
||||
|
||||
|
||||
Reference in New Issue
Block a user