Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ coverage
/playwright-report/
/playwright/.cache/
# Webkit with playwright creates a salt file
salt
salt
package-lock.json
18 changes: 18 additions & 0 deletions DockerfileWithToken
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# build stage
FROM node:lts-alpine AS build-stage
# Set environment variables for non-interactive npm installs
ENV NPM_CONFIG_LOGLEVEL warn
ENV CI true
ENV VITE_TOKEN "your_token"
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm i --frozen-lockfile
COPY . .
RUN pnpm build

# production stage
FROM nginx:stable-alpine AS production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ docker run -d --name it-tools --restart unless-stopped -p 8080:80 ghcr.io/corent
- [Tipi](https://www.runtipi.io/docs/apps-available)
- [Unraid](https://unraid.net/community/apps?q=it-tools)

## Public
If you want to add permission verification when users access the website, you can build and run the image using the following method. This approach will require users to enter a token before they can continue using the site.
```sh
cd it-tools
# vim DockerfileWithToken, change your_token to the token you want to use
docker build -f DockerfileWithToken -t it-tools:token .
docker run -d --name it-tools --restart unless-stopped -p 8080:80 it-tools:token
```

## Contribute

### Recommended IDE Setup
Expand Down
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ declare module '@vue/runtime-core' {
KeycodeInfo: typeof import('./src/tools/keycode-info/keycode-info.vue')['default']
ListConverter: typeof import('./src/tools/list-converter/list-converter.vue')['default']
LocaleSelector: typeof import('./src/modules/i18n/components/locale-selector.vue')['default']
Login: typeof import('./src/pages/Login.vue')['default']
LoremIpsumGenerator: typeof import('./src/tools/lorem-ipsum-generator/lorem-ipsum-generator.vue')['default']
MacAddressGenerator: typeof import('./src/tools/mac-address-generator/mac-address-generator.vue')['default']
MacAddressLookup: typeof import('./src/tools/mac-address-lookup/mac-address-lookup.vue')['default']
Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ export const config = figue({
default: 'development',
env: 'VITE_VERCEL_ENV',
},
token: {
doc: 'Application token',
format: 'string',
default: '',
env: 'VITE_TOKEN',
},
},
plausible: {
isTrackerEnabled: {
Expand Down
120 changes: 120 additions & 0 deletions src/pages/Login.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<script setup lang="ts">
import { ref } from 'vue';
import { config } from '@/config';

const token = ref('');

async function handleLogin() {
if (config.app.token === token.value) {
localStorage.setItem('isLoggedIn', 'true');
window.location.href = `${window.location.protocol}//${window.location.host}/`;
} else {

Check failure on line 11 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Closing curly brace appears on the same line as the subsequent block
alert('Invalid Token');

Check warning on line 12 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected alert
}
}
</script>

<template>
<div class="login-container">
<div class="login-card">
<h1 class="login-title">Login</h1>

Check warning on line 20 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Expected 1 line break after opening tag (`<h1>`), but no line breaks found

Check warning on line 20 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Expected 1 line break before closing tag (`</h1>`), but no line breaks found
<form @submit.prevent="handleLogin" class="login-form">

Check warning on line 21 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Attribute "class" should go before "@submit.prevent"
<div class="form-group">
<label for="token" class="form-label">Token:</label>
<input

Check warning on line 24 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Disallow self-closing on HTML void elements (<input/>)
id="token"
v-model="token"
type="text"
required
class="form-input"
placeholder="Enter your access token"
/>
</div>
<button type="submit" class="login-button">Login</button>

Check warning on line 33 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Expected 1 line break after opening tag (`<button>`), but no line breaks found

Check warning on line 33 in src/pages/Login.vue

View workflow job for this annotation

GitHub Actions / ci

Expected 1 line break before closing tag (`</button>`), but no line breaks found
</form>
</div>
</div>
</template>

<style scoped>
.login-container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #f5f5f5;
padding: 20px;
}

.login-card {
background: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
padding: 40px;
width: 100%;
max-width: 400px;
}

.login-title {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
font-size: 24px;
font-weight: 600;
}

.login-form {
display: flex;
flex-direction: column;
gap: 20px;
}

.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}

.form-label {
color: #2c3e50;
font-size: 14px;
font-weight: 500;
}

.form-input {
padding: 12px 16px;
border: 1px solid #e0e0e0;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}

.form-input:focus {
outline: none;
border-color: #4CAF50;
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
}

.login-button {
background: linear-gradient(135deg, #4CAF50, #81C784);
color: white;
border: none;
border-radius: 6px;
padding: 12px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
margin-top: 10px;
}

.login-button:hover {
background: linear-gradient(135deg, #3e8e41, #66BB6A);
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.login-button:active {
transform: translateY(0);
}
</style>
16 changes: 16 additions & 0 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
name: 'home',
component: HomePage,
},
{
path: '/login',
name: 'login',
component: () => import('./pages/Login.vue'),
},
{
path: '/about',
name: 'about',
Expand All @@ -38,4 +43,15 @@
],
});

if (config.app.token){

Check failure on line 46 in src/router.ts

View workflow job for this annotation

GitHub Actions / ci

Missing space before opening brace
router.beforeEach((to, from, next) => {
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
if (to.path !== '/login' && !isLoggedIn) {
next('/login');
} else {

Check failure on line 51 in src/router.ts

View workflow job for this annotation

GitHub Actions / ci

Closing curly brace appears on the same line as the subsequent block
next();
}
});
}

export default router;
Loading