mlmPenguin commited on
Commit
39cce41
·
verified ·
1 Parent(s): 6fdf9a1

Delete SecretSwap

Browse files
SecretSwap/dockerfile DELETED
@@ -1,23 +0,0 @@
1
-
2
-
3
- # Secret Swap – Docker image
4
- # Uses lightweight Alpine Node base
5
-
6
- FROM node:20-alpine
7
-
8
- # Create app directory
9
- WORKDIR /app
10
-
11
- # Install production dependencies
12
- COPY package*.json ./
13
- RUN npm ci --omit=dev
14
-
15
- # Copy source
16
- COPY . .
17
-
18
- # Hugging Face exposes its own $PORT; default to 7860 for local runs
19
- ENV PORT=${PORT:-7860}
20
- EXPOSE 7860
21
-
22
- # Launch the server
23
- CMD ["node", "server.js"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SecretSwap/exchanges.json DELETED
File without changes
SecretSwap/package.json DELETED
@@ -1,13 +0,0 @@
1
- {
2
- "name": "secret-swap",
3
- "version": "1.0.0",
4
- "type": "module",
5
- "description": "Ultra‑light secret exchange web app",
6
- "main": "server.js",
7
- "scripts": {
8
- "start": "node server.js"
9
- },
10
- "dependencies": {
11
- "express": "^4.18.2"
12
- }
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SecretSwap/public/style.css DELETED
@@ -1,93 +0,0 @@
1
-
2
-
3
- /* ===== Secret Swap minimalist styling ===== */
4
-
5
- *,
6
- *::before,
7
- *::after {
8
- box-sizing: border-box;
9
- }
10
-
11
- body {
12
- font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
13
- Helvetica, Arial, sans-serif;
14
- margin: 2rem;
15
- background: #f9f9fb;
16
- color: #333;
17
- line-height: 1.5;
18
- }
19
-
20
- h1,
21
- h2 {
22
- margin-top: 0;
23
- color: #111;
24
- }
25
-
26
- .container {
27
- max-width: 640px;
28
- margin: 0 auto;
29
- }
30
-
31
- form {
32
- margin-top: 1rem;
33
- }
34
-
35
- label {
36
- display: block;
37
- margin-bottom: 0.75rem;
38
- font-weight: 600;
39
- }
40
-
41
- input[type="text"],
42
- input[type="password"] {
43
- width: 100%;
44
- padding: 0.45rem 0.6rem;
45
- border: 1px solid #ccc;
46
- border-radius: 4px;
47
- font-size: 1rem;
48
- }
49
-
50
- button {
51
- padding: 0.55rem 1.1rem;
52
- border: none;
53
- border-radius: 4px;
54
- background: #1e88e5;
55
- color: #fff;
56
- font-size: 1rem;
57
- cursor: pointer;
58
- transition: background 0.18s ease-in-out;
59
- }
60
-
61
- button:hover {
62
- background: #1565c0;
63
- }
64
-
65
- a {
66
- color: #1e88e5;
67
- text-decoration: none;
68
- }
69
-
70
- a:hover {
71
- text-decoration: underline;
72
- }
73
-
74
- ul {
75
- padding-left: 1.25rem;
76
- }
77
-
78
- li {
79
- margin-bottom: 0.35rem;
80
- }
81
-
82
- .message {
83
- padding: 0.85rem 1rem;
84
- border: 1px solid #1e88e5;
85
- background: #e3f2fd;
86
- border-radius: 4px;
87
- margin: 1rem 0;
88
- }
89
-
90
- .error {
91
- border-color: #e53935;
92
- background: #ffebee;
93
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SecretSwap/server.js DELETED
@@ -1,169 +0,0 @@
1
- /* Secret-Swap – minimal Express server with flat-file storage */
2
- import express from 'express';
3
- import fs from 'fs';
4
- import path from 'path';
5
- import crypto from 'crypto';
6
- import { fileURLToPath } from 'url';
7
-
8
- const __filename = fileURLToPath(import.meta.url);
9
- const __dirname = path.dirname(__filename);
10
-
11
- const USERS_FILE = path.join(__dirname, 'users.json');
12
- const EXCH_FILE = path.join(__dirname, 'exchanges.json');
13
- const PORT = process.env.PORT || 3000;
14
-
15
- /* ---------- helpers ---------- */
16
- const readJSON = (f, d = {}) => (fs.existsSync(f) ? JSON.parse(fs.readFileSync(f)) : d);
17
- const writeJSON = (f, o) => fs.writeFileSync(f, JSON.stringify(o, null, 2));
18
-
19
- const sessions = new Map(); // token → username
20
- const genToken = () => crypto.randomUUID();
21
-
22
- function hashPass(pw, salt = crypto.randomBytes(16).toString('hex')) {
23
- const hash = crypto.scryptSync(pw, salt, 64).toString('hex');
24
- return `${salt}:${hash}`;
25
- }
26
- function checkPass(pw, stored) {
27
- const [salt, ref] = stored.split(':');
28
- const hash = crypto.scryptSync(pw, salt, 64).toString('hex');
29
- return crypto.timingSafeEqual(Buffer.from(hash, 'hex'), Buffer.from(ref, 'hex'));
30
- }
31
-
32
- /* ---------- tiny templating ---------- */
33
- const page = (title, body) => `<!DOCTYPE html><html><head><meta charset=utf-8><title>${title}</title><link rel="stylesheet" href="/style.css"></head><body><h1>${title}</h1>${body}</body></html>`;
34
- const input = (n,l,t='text') => `<label>${l}: <input type="${t}" name="${n}" required></label><br>`;
35
-
36
- /* ---------- app ---------- */
37
- const app = express();
38
- app.use(express.urlencoded({extended:true}));
39
- app.use(express.static(path.join(__dirname,'public')));
40
-
41
- app.use((req, _res, next) => {
42
- const token = (req.headers.cookie||'').split(';').map(c=>c.trim().split('='))[0]?.[1];
43
- req.user = sessions.get(token);
44
- req.token = token;
45
- next();
46
- });
47
- const needAuth = (req,res,next)=>req.user?next():res.redirect('/login');
48
-
49
- /* ---------- auth ---------- */
50
- app.get('/register', (req,res)=>res.send(page('Register',`
51
- <form method=post action=/register>
52
- ${input('username','Username')}
53
- ${input('password','Password','password')}
54
- <button>Register</button>
55
- </form>
56
- <p><a href=/login>Have an account? Login</a></p>`)));
57
-
58
- app.post('/register',(req,res)=>{
59
- const {username,password}=req.body;
60
- const users=readJSON(USERS_FILE,{});
61
- if(users[username])return res.send(page('Error','<p>User exists.</p>'));
62
- users[username]=hashPass(password);
63
- writeJSON(USERS_FILE,users);
64
- res.redirect('/login');
65
- });
66
-
67
- app.get('/login',(req,res)=>res.send(page('Login',`
68
- <form method=post action=/login>
69
- ${input('username','Username')}
70
- ${input('password','Password','password')}
71
- <button>Login</button>
72
- </form>
73
- <p><a href=/register>No account? Register</a></p>`)));
74
-
75
- app.post('/login',(req,res)=>{
76
- const {username,password}=req.body;
77
- const users=readJSON(USERS_FILE,{});
78
- if(!users[username]||!checkPass(password,users[username]))
79
- return res.send(page('Error','<p>Bad credentials.</p>'));
80
- const token=genToken();
81
- sessions.set(token,username);
82
- res.setHeader('Set-Cookie',`token=${token}; HttpOnly; Path=/`);
83
- res.redirect('/dashboard');
84
- });
85
-
86
- app.get('/logout',(req,res)=>{
87
- if(req.token) sessions.delete(req.token);
88
- res.setHeader('Set-Cookie','token=; Max-Age=0; Path=/');
89
- res.redirect('/login');
90
- });
91
-
92
- /* ---------- dashboard ---------- */
93
- app.get(['/','/dashboard'],needAuth,(req,res)=>{
94
- const exchanges=readJSON(EXCH_FILE,{});
95
- const list=Object.entries(exchanges)
96
- .filter(([id,x])=>x.owner===req.user||x.partner===req.user)
97
- .map(([id,x])=>{
98
- const role = x.owner===req.user? 'owner':'partner';
99
- return `<li>[${role}] “${x.secret}” → <a href=/respond/${id}>link</a>${x.responses.length?` (${x.responses.length} reply)`:' '}</li>`;
100
- }).join('');
101
- res.send(page('Dashboard',`
102
- <p>Logged in as <strong>${req.user}</strong> | <a href=/logout>Logout</a></p>
103
- <h2>Create new secret swap</h2>
104
- <form method=post action=/create>
105
- ${input('partner','Partner username')}
106
- ${input('secret','Your secret')}
107
- <button>Create & share</button>
108
- </form>
109
- <h2>Your swaps</h2>
110
- <ul>${list||'<li>(none yet)</li>'}</ul>`));
111
- });
112
-
113
- /* ---------- create ---------- */
114
- app.post('/create',needAuth,(req,res)=>{
115
- const {secret,partner}=req.body;
116
- const users=readJSON(USERS_FILE,{});
117
- if(!users[partner]) return res.send(page('Error','<p>Partner username not found.</p>'));
118
- const exchanges=readJSON(EXCH_FILE,{});
119
- const id=crypto.randomUUID();
120
- exchanges[id]={id,owner:req.user,partner,secret,responses:[]};
121
- writeJSON(EXCH_FILE,exchanges);
122
- const host=req.headers.host;
123
- res.send(page('Swap created',`
124
- <p>Send this link to <strong>${partner}</strong>:</p>
125
- <p><a href=/respond/${id}>http://${host}/respond/${id}</a></p>
126
- <p><a href=/dashboard>Return to dashboard</a></p>`));
127
- });
128
-
129
- /* ---------- respond ---------- */
130
- app.get('/respond/:id',needAuth,(req,res)=>{
131
- const ex=readJSON(EXCH_FILE,{})[req.params.id];
132
- if(!ex) return res.send(page('Error','<p>Swap not found.</p>'));
133
- if(req.user!==ex.partner && req.user!==ex.owner)
134
- return res.send(page('Forbidden','<p>You are not part of this swap.</p>'));
135
- if(req.user===ex.owner)
136
- return res.redirect(`/view/${req.params.id}`);
137
- const done=ex.responses.some(r=>r.from===req.user);
138
- if(done) return res.redirect(`/view/${req.params.id}`);
139
- res.send(page('Respond to secret',
140
- `<p>Original secret will be revealed after you submit yours.</p>
141
- <form method=post action=/respond/${req.params.id}>
142
- ${input('response','Your secret')}
143
- <button>Submit</button>
144
- </form>`));
145
- });
146
-
147
- app.post('/respond/:id',needAuth,(req,res)=>{
148
- const data=readJSON(EXCH_FILE,{});
149
- const ex=data[req.params.id];
150
- if(!ex||req.user!==ex.partner) return res.send(page('Error','<p>Not allowed.</p>'));
151
- ex.responses.push({from:req.user,secret:req.body.response});
152
- writeJSON(EXCH_FILE,data);
153
- res.send(page('Secret revealed',`<p>Original secret from ${ex.owner}: <strong>${ex.secret}</strong></p>
154
- <p><a href=/dashboard>Back to dashboard</a></p>`));
155
- });
156
-
157
- /* ---------- view (owner) ---------- */
158
- app.get('/view/:id',needAuth,(req,res)=>{
159
- const ex=readJSON(EXCH_FILE,{})[req.params.id];
160
- if(!ex||req.user!==ex.owner) return res.send(page('Error','<p>Not allowed.</p>'));
161
- const list=ex.responses.map(r=>`<li>${r.from}: ${r.secret}</li>`).join('')||'<li>(no response yet)</li>';
162
- res.send(page('Swap responses',`
163
- <p>Your secret: <strong>${ex.secret}</strong></p>
164
- <ul>${list}</ul>
165
- <p><a href=/dashboard>Back to dashboard</a></p>`));
166
- });
167
-
168
- /* ---------- start ---------- */
169
- app.listen(PORT,()=>console.log(`Secret-Swap listening on ${PORT}`));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SecretSwap/users.json DELETED
File without changes