Bihan-Banerjee commited on
Commit
c109b62
·
1 Parent(s): 7374940

initial commit

Browse files
.env ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ MONGO_URI=mongodb+srv://terimarzi:8pKpTnnZdqPBIAE8@securecode.irgi2mi.mongodb.net/
2
+ SECRET_KEY=T_u_H_i_B_a_T_a
3
+ JWT_SECRET=supersecretkey
4
+ USE_REDIS=false
DockerFile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.9
2
+ FROM python:3.9
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Copy requirements and install dependencies
8
+ COPY requirements.txt requirements.txt
9
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
10
+
11
+ # Copy the rest of the backend code
12
+ COPY . .
13
+
14
+ # Create a non-root user (Security requirement for HF Spaces)
15
+ RUN useradd -m -u 1000 user
16
+ USER user
17
+ ENV HOME=/home/user \
18
+ PATH=/home/user/.local/bin:$PATH
19
+
20
+ # Expose port 7860 (Required by Hugging Face)
21
+ EXPOSE 7860
22
+
23
+ # Command to run the application
24
+ # We use gunicorn for production performance
25
+ CMD ["gunicorn", "-b", "0.0.0.0:7860", "app:app", "--timeout", "120"]
__pycache__/model.cpython-313.pyc ADDED
Binary file (6.9 kB). View file
 
__pycache__/schemas.cpython-313.pyc ADDED
Binary file (870 Bytes). View file
 
app.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ from flask_jwt_extended import JWTManager, jwt_required, get_jwt_identity
4
+ from routes.auth import auth_bp
5
+ from dotenv import load_dotenv
6
+ from model import enhance_code
7
+ import tempfile
8
+ import os
9
+ import subprocess
10
+ import json
11
+ from pymongo import MongoClient
12
+ from routes.reviews import reviews_bp
13
+ from flask_limiter import Limiter
14
+ from flask_limiter.util import get_remote_address
15
+ from datetime import datetime
16
+ from datetime import timedelta
17
+ from bson import ObjectId
18
+ from models.reviews import reviews_collection
19
+ from schemas import ScanRequest
20
+ from pydantic import ValidationError
21
+ from flask_compress import Compress
22
+ from flask_caching import Cache
23
+ import hashlib
24
+ load_dotenv()
25
+
26
+ app = Flask(__name__)
27
+ Compress(app)
28
+ CORS(app)
29
+
30
+ if os.getenv("USE_REDIS", "false").lower() == "true":
31
+ cache = Cache(config={
32
+ "CACHE_TYPE": "RedisCache",
33
+ "CACHE_REDIS_URL": os.getenv("REDIS_URL", "redis://localhost:6379/0"),
34
+ "CACHE_DEFAULT_TIMEOUT": 3600
35
+ })
36
+ else:
37
+ cache = Cache(config={
38
+ "CACHE_TYPE": "SimpleCache",
39
+ "CACHE_DEFAULT_TIMEOUT": 3600
40
+ })
41
+
42
+ cache.init_app(app)
43
+
44
+ cache.init_app(app)
45
+
46
+ def files_hash(files):
47
+ h = hashlib.sha256()
48
+ for f in sorted(files, key=lambda x: x["filename"]):
49
+ h.update(f["filename"].encode())
50
+ h.update(b"\0")
51
+ h.update(f["content"].encode())
52
+ return h.hexdigest()
53
+
54
+ app.config['MONGO_URI'] = os.getenv("MONGO_URI")
55
+ app.config['SECRET_KEY'] = os.getenv('JWT_SECRET') or 'super-secret-key'
56
+ app.config["JWT_SECRET_KEY"] = os.getenv('JWT_SECRET') or 'super-secret-key'
57
+ app.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(minutes=60)
58
+
59
+ app.register_blueprint(reviews_bp)
60
+ jwt = JWTManager(app)
61
+
62
+ client = MongoClient(app.config['MONGO_URI'])
63
+ db = client["codewhisperer"]
64
+ users = db["users"]
65
+ enhance_history = db["enhance_history"]
66
+ scan_history = db["scan_history"]
67
+
68
+ app.register_blueprint(auth_bp, url_prefix="/api")
69
+
70
+ limiter = Limiter(
71
+ key_func=get_remote_address,
72
+ default_limits=["20 per minute"]
73
+ )
74
+ limiter.init_app(app)
75
+
76
+ @app.route('/api/scan', methods=['POST'])
77
+ @limiter.limit("5/minute")
78
+ @jwt_required()
79
+ def scan_code():
80
+ try:
81
+ data = request.get_json()
82
+ app.logger.info(f"Incoming request: {data}")
83
+
84
+ try:
85
+ req = ScanRequest(**data)
86
+ except ValidationError as e:
87
+ app.logger.error(f"Validation error: {e.errors()}")
88
+ return jsonify({"error": e.errors()}), 400
89
+
90
+ files = [f.dict() for f in req.files]
91
+ language = req.language.lower()
92
+ username = get_jwt_identity()
93
+
94
+ key = f"scan:{username}:{files_hash(files)}"
95
+ cached = cache.get(key)
96
+ if cached:
97
+ return jsonify({"result": cached, "cached": True})
98
+
99
+ with tempfile.TemporaryDirectory() as temp_dir:
100
+ for f in files:
101
+ path = os.path.join(temp_dir, f["filename"])
102
+ with open(path, "w", encoding="utf-8") as code_file:
103
+ code_file.write(f["content"])
104
+
105
+ if language == "python":
106
+ scan_command = ["python", "-m", "bandit", "-r", temp_dir, "-f", "json"]
107
+ elif language == "javascript":
108
+ scan_command = ["python", "-m", "semgrep", "--config=p/javascript", "--json", temp_dir]
109
+ else:
110
+ return jsonify({"error": "Unsupported language"}), 400
111
+
112
+ app.logger.info(f"Running: {' '.join(scan_command)}")
113
+ result = subprocess.run(scan_command, capture_output=True, text=True)
114
+
115
+ app.logger.info(f"stdout: {result.stdout[:500]}")
116
+ app.logger.info(f"stderr: {result.stderr}")
117
+
118
+ if result.returncode not in (0, 1, 2):
119
+ return jsonify({"error": result.stderr}), 500
120
+
121
+ try:
122
+ output_json = json.loads(result.stdout)
123
+ except Exception as e:
124
+ return jsonify({"error": f"JSON parse failed: {str(e)}", "raw": result.stdout}), 500
125
+
126
+ cache.set(key, output_json)
127
+ scan_history.insert_one({
128
+ "username": username,
129
+ "language": language,
130
+ "files": files,
131
+ "result": output_json,
132
+ "timestamp": datetime.utcnow().isoformat()
133
+ })
134
+
135
+ return jsonify({"result": output_json})
136
+
137
+ except Exception as e:
138
+ app.logger.error(f"Unexpected error: {str(e)}")
139
+ return jsonify({"error": str(e)}), 500
140
+
141
+
142
+
143
+ @app.route("/api/health")
144
+ def health():
145
+ return jsonify({"status": "ok"})
146
+
147
+ @app.route('/api/enhance', methods=['POST'])
148
+ @limiter.limit("5/minute")
149
+ @jwt_required()
150
+ def enhance():
151
+ try:
152
+ data = request.get_json()
153
+ code = data.get("code", "")
154
+ language = data.get("language", "python").lower()
155
+ username = get_jwt_identity()
156
+
157
+ if language not in ["python", "javascript"]:
158
+ return jsonify({"error": "Unsupported language"}), 400
159
+
160
+ if not code.strip():
161
+ return jsonify({"error": "No code provided"}), 400
162
+
163
+ # 🔹 New format (returns dict)
164
+ result = enhance_code(code, language)
165
+
166
+ # Save to history (with candidates + explanations)
167
+ enhance_history.insert_one({
168
+ "username": username,
169
+ "code": code,
170
+ "language": language,
171
+ "enhanced_code": result["enhanced_code"],
172
+ "diff": result["diff"],
173
+ "candidates": result.get("candidates", []),
174
+ "explanations": result.get("explanations", []),
175
+ "timestamp": datetime.utcnow().isoformat()
176
+ })
177
+
178
+ return jsonify(result), 200
179
+
180
+ except Exception as e:
181
+ return jsonify({"error": str(e)}), 500
182
+
183
+ @app.route('/api/history', methods=['GET'])
184
+ @limiter.limit("10/minute")
185
+ @jwt_required()
186
+ def history():
187
+ try:
188
+ username = get_jwt_identity()
189
+
190
+ # Fetch both histories
191
+ enhance_records = list(enhance_history.find({"username": username}).sort("timestamp", -1))
192
+ scan_records = list(scan_history.find({"username": username}).sort("timestamp", -1))
193
+
194
+ # Convert ObjectId to string & return only relevant fields
195
+ def clean(record, record_type):
196
+ return {
197
+ "id": str(record.get("_id")),
198
+ "language": record.get("language"),
199
+ "code": record.get("code"),
200
+ "enhanced_code": record.get("enhanced_code"),
201
+ "diff": record.get("diff"),
202
+ "candidates": record.get("candidates", []), # ✅ added
203
+ "explanations": record.get("explanations", []), # ✅ added
204
+ "result": record.get("result") if record_type == "scan" else None,
205
+ "timestamp": record.get("timestamp"),
206
+ }
207
+
208
+ enhance_list = [clean(r, "enhance") for r in enhance_records]
209
+ scan_list = [clean(r, "scan") for r in scan_records]
210
+
211
+ return jsonify({
212
+ "enhance": enhance_list,
213
+ "scan": scan_list
214
+ })
215
+
216
+ except Exception as e:
217
+ return jsonify({"error": str(e)}), 500
218
+
219
+
220
+ @app.route("/api/reviews", methods=["POST"])
221
+ @limiter.limit("5/minute")
222
+ def submit_review():
223
+ try:
224
+ data = request.get_json()
225
+
226
+ name = data.get("name")
227
+ email = data.get("email")
228
+ rating = data.get("rating")
229
+ review = data.get("review")
230
+ date = data.get("date", datetime.utcnow().isoformat())
231
+
232
+ if not all([name, email, rating, review]):
233
+ return jsonify({"error": "All fields are required"}), 400
234
+
235
+ review_doc = {
236
+ "name": name,
237
+ "email": email,
238
+ "rating": rating,
239
+ "review": review,
240
+ "date": date,
241
+ }
242
+
243
+ result = reviews_collection.insert_one(review_doc)
244
+
245
+ return jsonify({
246
+ "message": "Review submitted successfully",
247
+ "id": str(result.inserted_id)
248
+ }), 201
249
+
250
+ except Exception as e:
251
+ return jsonify({"error": str(e)}), 500
252
+
253
+ if __name__ == '__main__':
254
+ app.run(host="0.0.0.0", port=5000, debug=True)
model.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import (
2
+ AutoTokenizer,
3
+ AutoModelForSeq2SeqLM,
4
+ AutoModelForCausalLM
5
+ )
6
+ import difflib, re, torch
7
+
8
+ # Models and their types
9
+ MODEL_CONFIGS = {
10
+ "Salesforce/codet5-base": "seq2seq", # CodeT5
11
+ "EleutherAI/gpt-neo-1.3B": "causal", # GPT-Neo
12
+ "microsoft/CodeGPT-small-py": "causal", # CodeGPT-small (Python)
13
+ }
14
+
15
+ # Load tokenizers and models
16
+ tokenizers, models = {}, {}
17
+
18
+ for name, mtype in MODEL_CONFIGS.items():
19
+ tokenizers[name] = AutoTokenizer.from_pretrained(name)
20
+ if mtype == "seq2seq":
21
+ models[name] = AutoModelForSeq2SeqLM.from_pretrained(name)
22
+ else:
23
+ models[name] = AutoModelForCausalLM.from_pretrained(name)
24
+
25
+ # Rule-based fixes
26
+ SECURE_REPLACEMENTS = {
27
+ "hashlib.md5": ("hashlib.sha256", "MD5 is weak, replaced with SHA-256."),
28
+ "hashlib.sha1": ("hashlib.sha256", "SHA1 is weak, replaced with SHA-256."),
29
+ "eval(": ("ast.literal_eval(", "Unsafe eval removed, replaced with safe literal_eval."),
30
+ "pickle.load(": ("# pickle.load removed", "pickle.load is unsafe, consider json/safe loaders."),
31
+ }
32
+
33
+ def rule_based_patch(code: str):
34
+ explanations = []
35
+ patched = code
36
+ for bad, (good, reason) in SECURE_REPLACEMENTS.items():
37
+ if bad in patched:
38
+ patched = patched.replace(bad, good)
39
+ explanations.append({"change": f"{bad} → {good}", "reason": reason})
40
+ return patched, explanations
41
+
42
+ def preserve_structure(original: str, enhanced: str):
43
+ """Ensure imports and function signatures remain if model drops them."""
44
+ final_code = enhanced
45
+ original_imports = [l for l in original.splitlines() if l.strip().startswith("import")]
46
+ for imp in original_imports:
47
+ if imp not in final_code:
48
+ final_code = imp + "\n" + final_code
49
+ original_defs = [l for l in original.splitlines() if l.strip().startswith("def ")]
50
+ for d in original_defs:
51
+ if d.split("(")[0] not in final_code:
52
+ final_code = d + "\n # [!] Function body missing, please review\n" + final_code
53
+ return final_code
54
+
55
+ def create_diff(original: str, enhanced: str):
56
+ """Return structured diff for frontend rendering."""
57
+ diff_lines = difflib.unified_diff(
58
+ original.splitlines(), enhanced.splitlines(),
59
+ fromfile="Original", tofile="Enhanced", lineterm=""
60
+ )
61
+ formatted = []
62
+ for line in diff_lines:
63
+ if line.startswith("+") and not line.startswith("+++"):
64
+ formatted.append({"type": "add", "content": line[1:]})
65
+ elif line.startswith("-") and not line.startswith("---"):
66
+ formatted.append({"type": "remove", "content": line[1:]})
67
+ elif not line.startswith("@@"):
68
+ formatted.append({"type": "context", "content": line})
69
+ return formatted
70
+
71
+ def postprocess_code(code: str):
72
+ code = re.sub(r'^"""|"""$', '', code.strip())
73
+ lines = code.splitlines()
74
+ return "\n".join([l.replace("\t", " ").rstrip() for l in lines])
75
+
76
+ def run_model(model_name, code, language):
77
+ tokenizer = tokenizers[model_name]
78
+ model = models[model_name]
79
+ mtype = MODEL_CONFIGS[model_name]
80
+
81
+ prompt = f"fix {language} code: {code}"
82
+
83
+ if mtype == "seq2seq":
84
+ inputs = tokenizer.encode(prompt, return_tensors="pt", truncation=True, max_length=512)
85
+ outputs = model.generate(inputs, max_length=512, num_beams=4, early_stopping=True)
86
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
87
+ else:
88
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
89
+ outputs = model.generate(
90
+ **inputs,
91
+ max_new_tokens=256,
92
+ temperature=0.3,
93
+ top_p=0.95,
94
+ do_sample=False
95
+ )
96
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
97
+
98
+ def enhance_code(code: str, language: str):
99
+ try:
100
+ patched_code, rule_explanations = rule_based_patch(code)
101
+
102
+ candidates = []
103
+ for m in MODEL_CONFIGS.keys():
104
+ try:
105
+ enhanced = run_model(m, patched_code, language)
106
+ enhanced = postprocess_code(enhanced)
107
+ enhanced = preserve_structure(code, enhanced)
108
+ candidates.append({"model": m, "code": enhanced})
109
+ except Exception as e:
110
+ candidates.append({"model": m, "code": f"# [!] Failed: {str(e)}"})
111
+
112
+ best = max(candidates, key=lambda c: len(c["code"]))
113
+ diff = create_diff(code, best["code"])
114
+
115
+ explanations = rule_explanations + [
116
+ {"change": "Model improvements", "reason": "Best candidate chosen among ensemble"}
117
+ ]
118
+
119
+ return {
120
+ "enhanced_code": best["code"],
121
+ "diff": diff,
122
+ "candidates": candidates[:3],
123
+ "explanations": explanations
124
+ }
125
+
126
+ except Exception as e:
127
+ fallback = code + f"\n# [!] Enhancer crashed: {str(e)}"
128
+ return {
129
+ "enhanced_code": fallback,
130
+ "diff": create_diff(code, fallback),
131
+ "candidates": [],
132
+ "explanations": [{"change": "Error", "reason": str(e)}]
133
+ }
models/__pycache__/reviews.cpython-313.pyc ADDED
Binary file (489 Bytes). View file
 
models/history.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ import os
3
+ from dotenv import load_dotenv
4
+ load_dotenv()
5
+
6
+ client = MongoClient(os.getenv("MONGO_URI"))
7
+ db = client["codewhisperer"]
8
+
9
+ enhance_history = db["enhance_history"]
10
+ scan_history = db["scan_history"]
models/reviews.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ from datetime import datetime
3
+ import os
4
+
5
+ client = MongoClient(os.getenv("MONGO_URI", "mongodb://localhost:27017"))
6
+ db = client["securecode"]
7
+ reviews_collection = db["reviews"]
requirements.txt ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # Flask dependencies
3
+ flask==2.3.3
4
+ flask-cors==4.0.0
5
+ flask-jwt-extended==4.5.3
6
+ flask-limiter==3.5.0
7
+ flask-compress==1.13
8
+ flask-caching==2.1.0
9
+ python-dotenv==1.0.0
10
+
11
+ # Database
12
+ pymongo==4.5.0
13
+
14
+ # Validation
15
+ pydantic>=2.9.2
16
+
17
+
18
+ # AI/ML dependencies
19
+ torch>=2.0.0
20
+ transformers>=4.30.0
21
+
22
+ # Security scanning tools
23
+ bandit>=1.7.5
24
+ semgrep>=1.45.0
25
+
26
+ # Optional: for better performance
27
+ accelerate>=0.20.0
28
+ safetensors>=0.3.0
29
+
30
+ bcrypt>=4.0.1
31
+ python-dotenv
32
+ gunicorn
routes/__pycache__/auth.cpython-313.pyc ADDED
Binary file (2.41 kB). View file
 
routes/__pycache__/reviews.cpython-313.pyc ADDED
Binary file (1.96 kB). View file
 
routes/auth.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ from flask_jwt_extended import create_access_token
3
+ import bcrypt
4
+ from pymongo import MongoClient
5
+ import os
6
+ from dotenv import load_dotenv
7
+
8
+ load_dotenv()
9
+ MONGO_URI = os.getenv("MONGO_URI")
10
+
11
+ auth_bp = Blueprint('auth', __name__)
12
+ client = MongoClient(MONGO_URI)
13
+ db = client["codewhisperer"]
14
+ users = db["users"]
15
+
16
+ @auth_bp.route("/register", methods=["POST"])
17
+ def register():
18
+ data = request.json
19
+ username = data["username"]
20
+ email = data["email"]
21
+ password = data["password"]
22
+
23
+ if users.find_one({"username": username}):
24
+ return jsonify({"error": "User already exists"}), 400
25
+
26
+ hashed_pw = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
27
+ users.insert_one({"username": username, "email": email, "password": hashed_pw})
28
+ token = create_access_token(identity=username)
29
+ return jsonify({"token": token}), 201
30
+
31
+ @auth_bp.route("/login", methods=["POST"])
32
+ def login():
33
+ data = request.json
34
+ username = data["username"]
35
+ password = data["password"]
36
+
37
+ user = users.find_one({"username": username})
38
+ if not user:
39
+ return jsonify({"error": "Invalid credentials"}), 401
40
+
41
+ if not bcrypt.checkpw(password.encode("utf-8"), user["password"]):
42
+ return jsonify({"error": "Invalid credentials"}), 401
43
+
44
+ token = create_access_token(identity=username)
45
+ return jsonify({"token": token})
routes/reviews.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ from pymongo import MongoClient
3
+ from datetime import datetime
4
+ import os
5
+
6
+ reviews_bp = Blueprint("reviews", __name__)
7
+ client = MongoClient(os.getenv("MONGO_URI"))
8
+ db = client["securecode_ai"]
9
+ reviews_collection = db["reviews"]
10
+
11
+ @reviews_bp.route("/api/reviews", methods=["POST"])
12
+ def submit_review():
13
+ try:
14
+ data = request.get_json()
15
+ required_fields = ["name", "email", "rating", "review"]
16
+ if not all(field in data and data[field] for field in required_fields):
17
+ return jsonify({"error": "All fields are required"}), 400
18
+
19
+ new_review = {
20
+ "name": data["name"],
21
+ "email": data["email"],
22
+ "rating": data["rating"],
23
+ "review": data["review"],
24
+ "date": datetime.utcnow().isoformat()
25
+ }
26
+
27
+ reviews_collection.insert_one(new_review)
28
+ return jsonify({"message": "Review submitted successfully!"}), 201
29
+
30
+ except Exception as e:
31
+ return jsonify({"error": str(e)}), 500
schemas.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # backend/schemas.py
2
+ from pydantic import BaseModel
3
+ from typing import List, Optional
4
+
5
+ class FileModel(BaseModel):
6
+ filename: str
7
+ content: str
8
+
9
+ class ScanRequest(BaseModel):
10
+ files: List[FileModel]
11
+ language: str = "python"
temp/test.py ADDED
Binary file (34 Bytes). View file
 
user_model.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ from dotenv import load_dotenv
3
+ import os
4
+
5
+ load_dotenv()
6
+ MONGO_URI = os.getenv("MONGO_URI")
7
+
8
+ client = MongoClient(MONGO_URI)
9
+ db = client["codewhisperer"]
10
+ users = db["users"]