Skip to content
Closed
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
8 changes: 4 additions & 4 deletions lambda/admin_portal/static/links.html
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ <h5 class="modal-title" id="createLinkModalLabel">
<div class="col-md-6 mb-3">
<label for="linkSlug" class="form-label">Slug <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="linkSlug" name="link_slug" required
pattern="[a-zA-Z0-9_\-]+" title="英数字、ハイフン、アンダースコアのみ使用可能">
<div class="form-text">英数字、ハイフン、アンダースコアのみ使用可能</div>
pattern="[a-zA-Z0-9_\-/]+" title="英数字、ハイフン、アンダースコア、スラッシュのみ使用可能">
<div class="form-text">英数字、ハイフン、アンダースコア、スラッシュのみ使用可能</div>
</div>

<!-- HTTP Status -->
Expand Down Expand Up @@ -522,15 +522,15 @@ <h5 class="modal-title" id="editLinkModalLabel">
e.stopPropagation();

const slugInput = document.getElementById('linkSlug');
const slugPattern = /^[a-zA-Z0-9_-]+$/;
const slugPattern = /^[a-zA-Z0-9_\-/]+$/;

if (!slugInput.value) {
alert('Slugを入力してください。');
return;
}

if (!slugPattern.test(slugInput.value)) {
alert('Slugは英数字、ハイフン、アンダースコアのみ使用可能です。');
alert('Slugは英数字、ハイフン、アンダースコア、スラッシュのみ使用可能です。');
return;
}

Expand Down
19 changes: 19 additions & 0 deletions lambda/layers/common/python/ddb/models/delibird_link.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import logging
import os
import re
from dataclasses import dataclass
from datetime import datetime
from enum import Enum, auto
Expand All @@ -18,6 +19,8 @@
from util.logger_util import setup_logger

_REGION = os.environ["AWS_REGION"]
_MAX_SLUG_LENGTH = 255
_SLUG_PATTERN = re.compile(r'^[a-zA-Z0-9\-_]+(?:/[a-zA-Z0-9\-_]+)*$', re.ASCII)

logger = setup_logger("delibird.link_table", logging.INFO)

Expand Down Expand Up @@ -55,11 +58,27 @@ class DelibirdLink:

max_uses: Optional[int] = None

@staticmethod
def _validation(link: "DelibirdLink") -> None:
# domain
if not link.domain:
raise ValueError("Domain is required.")
# slug
if (not (slug := link.link_slug)) or (len(slug) > _MAX_SLUG_LENGTH) or (not _SLUG_PATTERN.fullmatch(slug)):
raise ValueError(f"Invalid slug: {slug}")
# origin
if not link.link_origin:
raise ValueError("Origin is required.")
# status
if not link.status.is_redirection:
raise ValueError(f"Status code {link.status} is not a redirection status.")

def __post_init__(self):
if self.query_whitelist is None:
self.query_whitelist = set()
if self.tag is None:
self.tag = set()
DelibirdLink._validation(self)

def check_active(self) -> tuple[bool, Optional[DelibirdLinkInactiveReason]]:
if self.disabled:
Expand Down
4 changes: 4 additions & 0 deletions s3/css/admin-portal.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
max-width: 50px;
}

.tooltip-inner {
max-width: 400px;
}

.table-responsive {
font-size: 0.9rem;
}
Expand Down