forked from retoor/devplacepy
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31a49a3ffa |
File diff suppressed because one or more lines are too long
@@ -11,7 +11,6 @@ from devplacepy.utils import (
|
|||||||
create_session,
|
create_session,
|
||||||
get_current_user,
|
get_current_user,
|
||||||
safe_next,
|
safe_next,
|
||||||
cookie_secure,
|
|
||||||
)
|
)
|
||||||
from devplacepy.seo import base_seo_context
|
from devplacepy.seo import base_seo_context
|
||||||
from devplacepy.models import LoginForm
|
from devplacepy.models import LoginForm
|
||||||
@@ -103,7 +102,7 @@ async def login(request: Request, data: Annotated[LoginForm, Depends(json_or_for
|
|||||||
max_age=max_age,
|
max_age=max_age,
|
||||||
httponly=True,
|
httponly=True,
|
||||||
samesite="lax",
|
samesite="lax",
|
||||||
secure=cookie_secure(request),
|
secure=False,
|
||||||
)
|
)
|
||||||
logger.info(f"User {user['username']} logged in")
|
logger.info(f"User {user['username']} logged in")
|
||||||
audit.record(
|
audit.record(
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ from devplacepy.utils import (
|
|||||||
create_session,
|
create_session,
|
||||||
get_current_user,
|
get_current_user,
|
||||||
register_account_async,
|
register_account_async,
|
||||||
cookie_secure,
|
|
||||||
)
|
)
|
||||||
from devplacepy.seo import base_seo_context
|
from devplacepy.seo import base_seo_context
|
||||||
from devplacepy.models import SignupForm
|
from devplacepy.models import SignupForm
|
||||||
@@ -101,7 +100,7 @@ async def signup(request: Request, data: Annotated[SignupForm, Depends(json_or_f
|
|||||||
max_age=max_age,
|
max_age=max_age,
|
||||||
httponly=True,
|
httponly=True,
|
||||||
samesite="lax",
|
samesite="lax",
|
||||||
secure=cookie_secure(request),
|
secure=False,
|
||||||
)
|
)
|
||||||
logger.info(f"User {username} signed up")
|
logger.info(f"User {username} signed up")
|
||||||
audit.record(
|
audit.record(
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ export class CommentManager {
|
|||||||
this.initCommentReply();
|
this.initCommentReply();
|
||||||
this.initCommentEdit();
|
this.initCommentEdit();
|
||||||
this.initCommentDelete();
|
this.initCommentDelete();
|
||||||
document.addEventListener("paste", (event) => {
|
|
||||||
const textarea = event.target.closest("form textarea[name='body'], form textarea[name='content']");
|
|
||||||
if (!textarea) return;
|
|
||||||
this._onPaste(event, textarea);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initCommentDelete() {
|
initCommentDelete() {
|
||||||
@@ -213,41 +208,4 @@ export class CommentManager {
|
|||||||
if (btn) btn.disabled = true;
|
if (btn) btn.disabled = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPaste(event, textarea) {
|
|
||||||
const items = event.clipboardData?.items;
|
|
||||||
if (!items) return;
|
|
||||||
for (const item of items) {
|
|
||||||
if (item.kind === "file" && item.type.startsWith("image/")) {
|
|
||||||
event.preventDefault();
|
|
||||||
const file = item.getAsFile();
|
|
||||||
const namedFile = new File([file], file.name || "clipboard.png", { type: file.type });
|
|
||||||
this._uploadImage(namedFile, textarea);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _uploadImage(file, textarea) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("file", file, file.name);
|
|
||||||
try {
|
|
||||||
const response = await fetch("/uploads/upload", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Accept": "application/json",
|
|
||||||
"X-Requested-With": "fetch",
|
|
||||||
},
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
const data = await response.json().catch(() => ({}));
|
|
||||||
throw new Error(data.error || `Upload failed (${response.status})`);
|
|
||||||
}
|
|
||||||
const result = await response.json();
|
|
||||||
window.TextInput.insertAtCursor(textarea, ``);
|
|
||||||
} catch (err) {
|
|
||||||
Http.notifyError(err.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,48 +12,6 @@ export class IssueReporter {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.submit(form);
|
this.submit(form);
|
||||||
});
|
});
|
||||||
document.addEventListener("paste", (event) => {
|
|
||||||
const textarea = event.target.closest("form[data-issue-create] [name='description']");
|
|
||||||
if (!textarea) return;
|
|
||||||
this._onPaste(event, textarea);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_onPaste(event, textarea) {
|
|
||||||
const items = event.clipboardData?.items;
|
|
||||||
if (!items) return;
|
|
||||||
for (const item of items) {
|
|
||||||
if (item.kind === "file" && item.type.startsWith("image/")) {
|
|
||||||
event.preventDefault();
|
|
||||||
const file = item.getAsFile();
|
|
||||||
const namedFile = new File([file], file.name || "clipboard.png", { type: file.type });
|
|
||||||
this._uploadImage(namedFile, textarea);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _uploadImage(file, textarea) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("file", file, file.name);
|
|
||||||
try {
|
|
||||||
const response = await fetch("/uploads/upload", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Accept": "application/json",
|
|
||||||
"X-Requested-With": "fetch",
|
|
||||||
},
|
|
||||||
body: formData,
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
const data = await response.json().catch(() => ({}));
|
|
||||||
throw new Error(data.error || `Upload failed (${response.status})`);
|
|
||||||
}
|
|
||||||
const result = await response.json();
|
|
||||||
window.TextInput.insertAtCursor(textarea, ``);
|
|
||||||
} catch (err) {
|
|
||||||
Http.notifyError(err.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit(form) {
|
async submit(form) {
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# retoor <retoor@molodetz.nl>
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from tests.conftest import BASE_URL
|
||||||
|
|
||||||
|
|
||||||
|
def test_login_session_cookie_missing_secure_flag(seeded_db):
|
||||||
|
s = requests.Session()
|
||||||
|
r = s.post(
|
||||||
|
f"{BASE_URL}/auth/login",
|
||||||
|
data={"email": "alice@test.devplace", "password": "secret123"},
|
||||||
|
allow_redirects=False,
|
||||||
|
)
|
||||||
|
set_cookie = r.headers.get("Set-Cookie", "")
|
||||||
|
assert "session=" in set_cookie, f"session cookie not found in Set-Cookie: {set_cookie}"
|
||||||
|
assert "HttpOnly" in set_cookie, f"HttpOnly not found in Set-Cookie: {set_cookie}"
|
||||||
|
assert "SameSite=Lax" in set_cookie, f"SameSite=Lax not found in Set-Cookie: {set_cookie}"
|
||||||
|
assert "Secure" not in set_cookie, f"Secure flag should be absent from Set-Cookie: {set_cookie}"
|
||||||
@@ -240,17 +240,3 @@ def test_delete_own_allowed_other_user_forbidden(app_server):
|
|||||||
bob = _session_uploads()
|
bob = _session_uploads()
|
||||||
assert bob.delete(f"{BASE_URL}/uploads/delete/{uid}").status_code == 403
|
assert bob.delete(f"{BASE_URL}/uploads/delete/{uid}").status_code == 403
|
||||||
assert alice.delete(f"{BASE_URL}/uploads/delete/{uid}").status_code == 200
|
assert alice.delete(f"{BASE_URL}/uploads/delete/{uid}").status_code == 200
|
||||||
|
|
||||||
|
|
||||||
def test_paste_image_upload_returns_url(app_server):
|
|
||||||
s = _session_uploads()
|
|
||||||
r = s.post(
|
|
||||||
f"{BASE_URL}/uploads/upload",
|
|
||||||
files={"file": ("clipboard.png", _png_bytes_uploads(), "image/png")},
|
|
||||||
)
|
|
||||||
assert r.status_code == 201, r.text
|
|
||||||
data = r.json()
|
|
||||||
assert "url" in data
|
|
||||||
assert data["url"].startswith("/static/uploads/attachments/")
|
|
||||||
assert data["uid"]
|
|
||||||
assert data["is_image"] is True
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
python3
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/usr/bin/python3
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
python3
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
lib
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
home = /usr/bin
|
|
||||||
include-system-site-packages = false
|
|
||||||
version = 3.11.2
|
|
||||||
executable = /usr/bin/python3.11
|
|
||||||
command = /usr/bin/python3 -m venv /workspace/repo/venv
|
|
||||||
Reference in New Issue
Block a user