1+ # ==========================================================
2+ # ShareFlow - Startup File Sharing SaaS
3+ # Modern Cloud File Distribution Platform
4+ # ==========================================================
5+
6+ import os
7+ import uuid
8+ import sqlite3
9+ from datetime import datetime
10+
11+ from flask import (
12+ Flask , request , redirect , url_for ,
13+ render_template_string , session ,
14+ send_from_directory
15+ )
16+
17+ from werkzeug .security import generate_password_hash , check_password_hash
18+ from werkzeug .utils import secure_filename
19+
20+
21+ # =================== CONFIG ===================
22+
23+ APP_NAME = "ShareFlow"
24+ APP_VERSION = "1.0"
25+
26+ UPLOAD_FOLDER = "storage"
27+ DATABASE = "shareflow.db"
28+
29+ os .makedirs (UPLOAD_FOLDER , exist_ok = True )
30+
31+
32+ # =================== APP ===================
33+
34+ app = Flask (__name__ )
35+ app .secret_key = "dev-secret"
36+
37+ app .config ["UPLOAD_FOLDER" ] = UPLOAD_FOLDER
38+
39+
40+ # =================== DATABASE ===================
41+
42+ def db ():
43+ conn = sqlite3 .connect (DATABASE )
44+ conn .row_factory = sqlite3 .Row
45+ return conn
46+
47+
48+ def init_db ():
49+
50+ conn = db ()
51+
52+ conn .execute ("""
53+ CREATE TABLE IF NOT EXISTS users(
54+ id INTEGER PRIMARY KEY,
55+ username TEXT UNIQUE,
56+ password TEXT
57+ )
58+ """ )
59+
60+ conn .execute ("""
61+ CREATE TABLE IF NOT EXISTS files(
62+ id TEXT PRIMARY KEY,
63+ user_id INTEGER,
64+ filename TEXT,
65+ path TEXT,
66+ size INTEGER,
67+ downloads INTEGER,
68+ created TEXT
69+ )
70+ """ )
71+
72+ conn .commit ()
73+ conn .close ()
74+
75+
76+ # =================== USER ===================
77+
78+ def current_user ():
79+
80+ if "user_id" not in session :
81+ return None
82+
83+ conn = db ()
84+
85+ user = conn .execute (
86+ "SELECT * FROM users WHERE id=?" ,
87+ (session ["user_id" ],)
88+ ).fetchone ()
89+
90+ conn .close ()
91+
92+ return user
93+
94+
95+ # =================== AUTH ===================
96+
97+ @app .route ("/register" , methods = ["GET" ,"POST" ])
98+ def register ():
99+
100+ if request .method == "POST" :
101+
102+ username = request .form ["username" ]
103+ password = generate_password_hash (request .form ["password" ])
104+
105+ conn = db ()
106+
107+ conn .execute (
108+ "INSERT INTO users(username,password) VALUES(?,?)" ,
109+ (username ,password )
110+ )
111+
112+ conn .commit ()
113+ conn .close ()
114+
115+ return redirect ("/login" )
116+
117+ return """
118+ <h2>Register</h2>
119+ <form method="post">
120+ <input name="username">
121+ <input name="password" type="password">
122+ <button>Register</button>
123+ </form>
124+ """
125+
126+
127+ @app .route ("/login" , methods = ["GET" ,"POST" ])
128+ def login ():
129+
130+ if request .method == "POST" :
131+
132+ username = request .form ["username" ]
133+ password = request .form ["password" ]
134+
135+ conn = db ()
136+
137+ user = conn .execute (
138+ "SELECT * FROM users WHERE username=?" ,
139+ (username ,)
140+ ).fetchone ()
141+
142+ conn .close ()
143+
144+ if user and check_password_hash (user ["password" ],password ):
145+
146+ session ["user_id" ] = user ["id" ]
147+
148+ return redirect ("/dashboard" )
149+
150+ return """
151+ <h2>Login</h2>
152+ <form method="post">
153+ <input name="username">
154+ <input name="password" type="password">
155+ <button>Login</button>
156+ </form>
157+ """
158+
159+
160+ # =================== DASHBOARD ===================
161+
162+ @app .route ("/" )
163+ @app .route ("/dashboard" )
164+ def dashboard ():
165+
166+ user = current_user ()
167+
168+ if not user :
169+ return redirect ("/login" )
170+
171+ conn = db ()
172+
173+ files = conn .execute (
174+ "SELECT * FROM files WHERE user_id=?" ,
175+ (user ["id" ],)
176+ ).fetchall ()
177+
178+ conn .close ()
179+
180+ return render_template_string (DASHBOARD_HTML , files = files )
181+
182+
183+ # =================== UPLOAD ===================
184+
185+ @app .route ("/upload" , methods = ["POST" ])
186+ def upload ():
187+
188+ user = current_user ()
189+
190+ if not user :
191+ return redirect ("/login" )
192+
193+ file = request .files ["file" ]
194+
195+ filename = secure_filename (file .filename )
196+
197+ file_id = str (uuid .uuid4 ())[:10 ]
198+
199+ path = os .path .join (
200+ UPLOAD_FOLDER ,
201+ file_id + "_" + filename
202+ )
203+
204+ file .save (path )
205+
206+ size = os .path .getsize (path )
207+
208+ conn = db ()
209+
210+ conn .execute ("""
211+ INSERT INTO files
212+ VALUES(?,?,?,?,?,?,?)
213+ """ ,(
214+ file_id ,
215+ user ["id" ],
216+ filename ,
217+ path ,
218+ size ,
219+ 0 ,
220+ datetime .now ()
221+ ))
222+
223+ conn .commit ()
224+ conn .close ()
225+
226+ return redirect ("/dashboard" )
227+
228+
229+ # =================== DOWNLOAD ===================
230+
231+ @app .route ("/f/<file_id>" )
232+ def download (file_id ):
233+
234+ conn = db ()
235+
236+ file = conn .execute (
237+ "SELECT * FROM files WHERE id=?" ,
238+ (file_id ,)
239+ ).fetchone ()
240+
241+ conn .close ()
242+
243+ if not file :
244+ return "File not found"
245+
246+ conn = db ()
247+
248+ conn .execute (
249+ "UPDATE files SET downloads = downloads + 1 WHERE id=?" ,
250+ (file_id ,)
251+ )
252+
253+ conn .commit ()
254+ conn .close ()
255+
256+ directory = os .path .dirname (file ["path" ])
257+ filename = os .path .basename (file ["path" ])
258+
259+ return send_from_directory (directory , filename , as_attachment = True )
260+
261+
262+ # =================== DELETE ===================
263+
264+ @app .route ("/delete/<file_id>" )
265+ def delete (file_id ):
266+
267+ conn = db ()
268+
269+ file = conn .execute (
270+ "SELECT * FROM files WHERE id=?" ,
271+ (file_id ,)
272+ ).fetchone ()
273+
274+ if file :
275+
276+ try :
277+ os .remove (file ["path" ])
278+ except :
279+ pass
280+
281+ conn .execute (
282+ "DELETE FROM files WHERE id=?" ,
283+ (file_id ,)
284+ )
285+
286+ conn .commit ()
287+
288+ conn .close ()
289+
290+ return redirect ("/dashboard" )
291+
292+
293+ # =================== UI ===================
294+
295+ DASHBOARD_HTML = """
296+ <!DOCTYPE html>
297+ <html>
298+
299+ <head>
300+
301+ <title>ShareFlow</title>
302+
303+ <script src="https://cdn.tailwindcss.com"></script>
304+
305+ </head>
306+
307+ <body class="bg-gray-100">
308+
309+ <div class="max-w-4xl mx-auto p-8">
310+
311+ <h1 class="text-3xl font-bold mb-6">ShareFlow Dashboard</h1>
312+
313+ <form
314+ action="/upload"
315+ method="post"
316+ enctype="multipart/form-data"
317+ class="mb-6 p-6 bg-white rounded shadow">
318+
319+ <input type="file" name="file" class="mb-3">
320+
321+ <button class="bg-blue-500 text-white px-4 py-2 rounded">
322+ Upload File
323+ </button>
324+
325+ </form>
326+
327+ <div class="bg-white shadow rounded">
328+
329+ <table class="w-full">
330+
331+ <tr class="border-b">
332+ <th class="p-3 text-left">File</th>
333+ <th>Size</th>
334+ <th>Downloads</th>
335+ <th>Share</th>
336+ <th></th>
337+ </tr>
338+
339+ {% for f in files %}
340+
341+ <tr class="border-b">
342+
343+ <td class="p-3">{{f.filename}}</td>
344+
345+ <td>{{(f.size/1024/1024)|round(2)}} MB</td>
346+
347+ <td>{{f.downloads}}</td>
348+
349+ <td>
350+ <a class="text-blue-600"
351+ href="/f/{{f.id}}">
352+ link
353+ </a>
354+ </td>
355+
356+ <td>
357+ <a class="text-red-500"
358+ href="/delete/{{f.id}}">
359+ delete
360+ </a>
361+ </td>
362+
363+ </tr>
364+
365+ {% endfor %}
366+
367+ </table>
368+
369+ </div>
370+
371+ </div>
372+
373+ </body>
374+
375+ </html>
376+ """
377+
378+
379+ # =================== START ===================
380+
381+ if __name__ == "__main__" :
382+
383+ init_db ()
384+
385+ print ("ShareFlow starting..." )
386+ print ("http://127.0.0.1:5000" )
387+
388+ app .run (debug = True )
0 commit comments