url link 저장 및 변경 관리 계정에서 할수 있도록 추가
All checks were successful
Build And Test / build-and-push (push) Successful in 4m8s

This commit is contained in:
icurfer 2025-01-25 01:30:48 +09:00
parent d34d4f8def
commit 06d1853fb0
10 changed files with 378 additions and 57 deletions

View File

@ -1,7 +1,8 @@
<div class="container-fluid d-flex justify-content-between align-items-center">
<h1 class="d-flex align-items-center fs-4 text-white mb-0">
<a class="navbar-brand" href="/">
<i class="fa-solid fa-dog"></i> DDoCHI</a>
<i class="fa-solid fa-dog"></i>
DDoCHI</a>
</h1>
<!-- 로그인/로그아웃 및 회원가입 버튼 -->
<ul class="navbar-nav flex-row">
@ -14,8 +15,7 @@
{% if request.user.is_authenticated %}
<!-- 회원정보 변경 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-info mb-2" data-bs-toggle="modal"
data-bs-target="#editProfileModal">Edit Profile</button>
<button type="button" class="btn btn-outline-info mb-2" data-bs-toggle="modal" data-bs-target="#editProfileModal">Edit Profile</button>
</li>
<!-- 로그아웃 버튼 -->
<li class="nav-item">
@ -27,13 +27,11 @@
{% else %}
<!-- 로그인 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-primary mb-2" data-bs-toggle="modal"
data-bs-target="#loginModal">Login</button>
<button type="button" class="btn btn-outline-primary mb-2" data-bs-toggle="modal" data-bs-target="#loginModal">Login</button>
</li>
<!-- 회원가입 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-success" data-bs-toggle="modal" data-bs-target="#signupModal">Sign
Up</button>
<button type="button" class="btn btn-outline-success" data-bs-toggle="modal" data-bs-target="#signupModal">Sign Up</button>
</li>
{% endif %}
</ul>
@ -123,7 +121,7 @@
{% csrf_token %}
<div class="mb-3">
<label for="emailEdit" class="form-label">Email</label>
<input type="email" class="form-control" id="emailEdit" name="email" value="{{ request.user.email }}" required>
<input type="email" class="form-control" id="emailEdit" name="email" value="{{ request.user.email }}" required="required">
</div>
<div class="mb-3">
<label for="nhncIdEdit" class="form-label">NHNC ID</label>
@ -133,6 +131,52 @@
<label for="nhncApiTenantIdEdit" class="form-label">NHNC API Tenant ID</label>
<input type="text" class="form-control" id="nhncApiTenantIdEdit" name="nhnc_api_tenant_id" value="{{ request.user.nhnc_api_tenant_id }}">
</div>
<!-- 추가된 URL 필드 -->
<div class="mb-3">
<label for="urlGiteaEdit" class="form-label">Gitea URL</label>
<input type="url" class="form-control" id="urlGiteaEdit" name="url_gitea" value="{{ request.user.url_gitea }}">
</div>
<div class="mb-3">
<label for="urlHarborEdit" class="form-label">Harbor URL</label>
<input type="url" class="form-control" id="urlHarborEdit" name="url_harbor" value="{{ request.user.url_harbor }}">
</div>
<div class="mb-3">
<label for="urlArgoCDEdit" class="form-label">ArgoCD URL</label>
<input type="url" class="form-control" id="urlArgoCDEdit" name="url_argocd" value="{{ request.user.url_argocd }}">
</div>
<div class="mb-3">
<label for="urlWebIdeEdit" class="form-label">Web IDE URL</label>
<input type="url" class="form-control" id="urlWebIdeEdit" name="url_web_ide" value="{{ request.user.url_web_ide }}">
</div>
<div class="mb-3">
<label for="urlRancherEdit" class="form-label">Rancher URL</label>
<input type="url" class="form-control" id="urlRancherEdit" name="url_rancher" value="{{ request.user.url_rancher }}">
</div>
<div class="mb-3">
<label for="urlGrafanaEdit" class="form-label">Grafana URL</label>
<input type="url" class="form-control" id="urlGrafanaEdit" name="url_grafana" value="{{ request.user.url_grafana }}">
</div>
<div class="mb-3">
<label for="urlPrometheusEdit" class="form-label">Prometheus URL</label>
<input type="url" class="form-control" id="urlPrometheusEdit" name="url_prometheus" value="{{ request.user.url_prometheus }}">
</div>
<div class="mb-3">
<label for="urlOpensearchEdit" class="form-label">OpenSearch URL</label>
<input type="url" class="form-control" id="urlOpensearchEdit" name="url_opensearch" value="{{ request.user.url_opensearch }}">
</div>
<div class="mb-3">
<label for="urlKialiEdit" class="form-label">Kiali URL</label>
<input type="url" class="form-control" id="urlKialiEdit" name="url_kiali" value="{{ request.user.url_kiali }}">
</div>
<div class="mb-3">
<label for="urlNexusEdit" class="form-label">Nexus URL</label>
<input type="url" class="form-control" id="urlNexusEdit" name="url_nexus" value="{{ request.user.url_nexus }}">
</div>
<div class="mb-3">
<label for="urlMattermostEdit" class="form-label">Mattermost URL</label>
<input type="url" class="form-control" id="urlMattermostEdit" name="url_mattermost" value="{{ request.user.url_mattermost }}">
</div>
<!-- 비밀번호 변경 -->
<div class="mb-3">
<label for="passwordEdit" class="form-label">새 비밀번호</label>
<input type="password" class="form-control" id="passwordEdit" name="password">

View File

@ -2,7 +2,7 @@
<nav class="sticky-xl-top small" id="toc">
<ul class="list-unstyled">
<li class="my-2">
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#about-collapse" aria-controls="about-collapse">About</button>
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#about-collapse" aria-controls="about-collapse">About</button>
<ul class="list-unstyled ps-3 collapse" id="about-collapse">
<li>
<a class="d-inline-flex align-items-center rounded" href="/notice">공지사항</a>
@ -11,7 +11,7 @@
</li>
<hr>
<li class="my-2">
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#contents-collapse" aria-controls="contents-collapse">Contents</button>
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#contents-collapse" aria-controls="contents-collapse">Contents</button>
<ul class="list-unstyled ps-3 collapse" id="contents-collapse">
<li>
<a class="d-inline-flex align-items-center rounded" href="/blog">Post</a>
@ -31,7 +31,7 @@
</li>
<hr>
<li class="my-2">
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#nhnc-collapse" aria-controls="nhnc-collapse">NHN Cloud API</button>
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#nhnc-collapse" aria-controls="nhnc-collapse">NHN Cloud API</button>
<ul class="list-unstyled ps-3 collapse" id="nhnc-collapse">
{% if request.user.is_authenticated and request.user.is_staff %}
<li>
@ -78,51 +78,51 @@
</li>
<hr>
<li class="my-2">
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#components-collapse" aria-controls="components-collapse">DevOpsTools</button>
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#components-collapse" aria-controls="components-collapse">DevOpsTools</button>
<ul class="list-unstyled ps-3 collapse" id="components-collapse">
<span>Dev</span>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://gitea.icurfer.com/icurfer" target="_blank">Repository - Gitea</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_gitea}}" target="_blank">Repository - Gitea</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://harbor.icurfer.com/" target="_blank">Registry - Harbor</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_harbor}}" target="_blank">Registry - Harbor</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://argocd.icurfer.com/" target="_blank">Deploy - ArgoCD</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_argocd}}" target="_blank">Deploy - ArgoCD</a>
</li>
<hr>
<span>Ops</span>
{% if request.user.is_authenticated and request.user.is_staff %}
<li>
<a class="d-inline-flex align-items-center rounded" href="https://code.icurfer.com/" target="_blank">Web VScode - CodeServer</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_web_ide}}" target="_blank">Web VScode - CodeServer</a>
</li>
{% endif %}
<li>
<a class="d-inline-flex align-items-center rounded" href="https://rancher.icurfer.com/" target="_blank">Cluster Management - Rancher</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_rancher}}" target="_blank">Cluster Management - Rancher</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://grafana.icurfer.com/" target="_blank">Monitoring - Grafana</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_grafana}}" target="_blank">Monitoring - Grafana</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://prometheus.icurfer.com/" target="_blank">Metrics - Prometheus</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_prometheus}}" target="_blank">Metrics - Prometheus</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://os.icurfer.com/" target="_blank">Container Log - OpenSearch</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_opensearch}}" target="_blank">Container Log - OpenSearch</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://kiali.icurfer.com/" target="_blank">Main Cluster Traffic - Kiali</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_kiali}}" target="_blank">Main Cluster Traffic - Kiali</a>
</li>
</ul>
</li>
<hr>
<li class="my-2">
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#other-collapse" aria-controls="other-collapse">Other Tools</button>
<button class="btn d-inline-flex align-items-center collapsed" data-bs-toggle="collapse" aria-expanded="false" data-bs-target="#other-collapse" aria-controls="other-collapse">Other Tools</button>
<ul class="list-unstyled ps-3 collapse" id="other-collapse">
<li>
<a class="d-inline-flex align-items-center rounded" href="https://mm.icurfer.com/" target="_blank">Messenger - Mattermost</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_mattermost}}" target="_blank">Messenger - Mattermost</a>
</li>
<li>
<a class="d-inline-flex align-items-center rounded" href="https://nexus.icurfer.com/" target="_blank">Nexus</a>
<a class="d-inline-flex align-items-center rounded" href="{{request.user.url_nexus}}" target="_blank">Nexus</a>
</li>
</ul>
</li>

View File

@ -0,0 +1,149 @@
<div class="container-fluid d-flex justify-content-between align-items-center">
<h1 class="d-flex align-items-center fs-4 text-white mb-0">
<a class="navbar-brand" href="/">
<i class="fa-solid fa-dog"></i> DDoCHI</a>
</h1>
<!-- 로그인/로그아웃 및 회원가입 버튼 -->
<ul class="navbar-nav flex-row">
{% if user.is_authenticated and user.is_superuser %}
<!-- 관리자 콘솔 버튼 -->
<li class="nav-item me-3">
<a href="/admin" target="_blank" class="btn btn-outline-warning mb-2">ADMIN</a>
</li>
{% endif %}
{% if request.user.is_authenticated %}
<!-- 회원정보 변경 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-info mb-2" data-bs-toggle="modal"
data-bs-target="#editProfileModal">Edit Profile</button>
</li>
<!-- 로그아웃 버튼 -->
<li class="nav-item">
<form method="post" action="{% url 'custom_auth:logout' %}">
{% csrf_token %}
<button type="submit" class="btn btn-outline-danger w-100">Logout</button>
</form>
</li>
{% else %}
<!-- 로그인 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-primary mb-2" data-bs-toggle="modal"
data-bs-target="#loginModal">Login</button>
</li>
<!-- 회원가입 버튼 -->
<li class="nav-item me-3">
<button type="button" class="btn btn-outline-success" data-bs-toggle="modal" data-bs-target="#signupModal">Sign
Up</button>
</li>
{% endif %}
</ul>
</div>
<!-- 로그인 모달 -->
<div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="loginModalLabel">Login</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- 로그인 실패 메시지 표시 -->
{% if messages %}
{% for message in messages %}
<div class="alert alert-danger" role="alert">
{{ message }}
</div>
{% endfor %}
{% endif %}
<!-- 로그인 폼 -->
<form method="post" action="{% url 'custom_auth:login' %}">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required="required">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required="required">
</div>
<button type="submit" class="btn btn-primary w-100">Login</button>
</form>
</div>
</div>
</div>
</div>
<!-- 회원가입 모달 -->
<div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="signupModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="signupModalLabel">Sign Up</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- 회원가입 폼 -->
<form method="post" action="{% url 'custom_auth:signup' %}">
{% csrf_token %}
<div class="mb-3">
<label for="usernameSignup" class="form-label">Username</label>
<input type="text" class="form-control" id="usernameSignup" name="username" required="required">
</div>
<div class="mb-3">
<label for="passwordSignup" class="form-label">Password</label>
<input type="password" class="form-control" id="passwordSignup" name="password1" required="required">
</div>
<div class="mb-3">
<label for="passwordConfirmSignup" class="form-label">Confirm Password</label>
<input type="password" class="form-control" id="passwordConfirmSignup" name="password2" required="required">
</div>
<a href="{% url 'butler:privacy' %}" class="text-dark" target="_blank">개인정보 처리방침</a>
<p class="text-danger">회원 가입후 권한 신청 메일을 보내주세요.</p>
<p class="text-danger">회원 가입시 본 개인정보 처리방침에 동의하는 것으로 간주됩니다.</p>
<button type="submit" class="btn btn-success w-100">Sign Up</button>
</form>
</div>
</div>
</div>
</div>
<!-- 회원정보 변경 모달 -->
<div class="modal fade" id="editProfileModal" tabindex="-1" aria-labelledby="editProfileModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editProfileModalLabel">Edit Profile</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<!-- 회원정보 변경 폼 -->
<form method="post" action="{% url 'custom_auth:edit_profile' %}">
{% csrf_token %}
<div class="mb-3">
<label for="emailEdit" class="form-label">Email</label>
<input type="email" class="form-control" id="emailEdit" name="email" value="{{ request.user.email }}" required>
</div>
<div class="mb-3">
<label for="nhncIdEdit" class="form-label">NHNC ID</label>
<input type="text" class="form-control" id="nhncIdEdit" name="nhnc_id" value="{{ request.user.nhnc_id }}">
</div>
<div class="mb-3">
<label for="nhncApiTenantIdEdit" class="form-label">NHNC API Tenant ID</label>
<input type="text" class="form-control" id="nhncApiTenantIdEdit" name="nhnc_api_tenant_id" value="{{ request.user.nhnc_api_tenant_id }}">
</div>
<div class="mb-3">
<label for="passwordEdit" class="form-label">새 비밀번호</label>
<input type="password" class="form-control" id="passwordEdit" name="password">
</div>
<div class="mb-3">
<label for="passwordConfirmEdit" class="form-label">비밀번호 확인</label>
<input type="password" class="form-control" id="passwordConfirmEdit" name="password_confirm">
</div>
<button type="submit" class="btn btn-primary w-100">Save Changes</button>
</form>
</div>
</div>
</div>
</div>

View File

@ -12,14 +12,32 @@ class CustomUserAdmin(UserAdmin):
# 사용자 필드 구성
fieldsets = (
(None, {'fields': ('username', 'password')}),
('Personal Info', {'fields': ('email', 'encrypted_private_key')}),
('Personal Info', {
'fields': (
'email',
'encrypted_private_key',
'nhnc_id',
'nhnc_api_tenant_id',
'url_gitea',
'url_harbor',
'url_argocd',
'url_web_ide',
'url_rancher',
'url_grafana',
'url_prometheus',
'url_opensearch',
'url_kiali',
'url_nexus',
'url_mattermost',
)
}),
('Permissions', {'fields': ('is_staff', 'is_active')}),
)
# 읽기 전용 필드 추가
readonly_fields = ('encrypted_private_key',)
search_fields = ('username', 'email')
search_fields = ('username', 'email', 'nhnc_id', 'nhnc_api_tenant_id')
ordering = ('username',)

View File

@ -23,7 +23,22 @@ class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ["email", "nhnc_id", "nhnc_api_tenant_id"]
fields = [
'email',
'nhnc_id',
'nhnc_api_tenant_id',
'url_gitea',
'url_harbor',
'url_argocd',
'url_web_ide',
'url_rancher',
'url_grafana',
'url_prometheus',
'url_opensearch',
'url_kiali',
'url_nexus',
'url_mattermost',
]
def clean(self):
cleaned_data = super().clean()

View File

@ -0,0 +1,58 @@
# Generated by Django 4.2.14 on 2025-01-25 00:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('custom_auth', '0005_customuser_encrypted_private_key'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='url_argocd',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_gitea',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_grafana',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_harbor',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_kiali',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_opensearch',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_prometheus',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_rancher',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_web_ide',
field=models.URLField(blank=True, null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 4.2.14 on 2025-01-25 01:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('custom_auth', '0006_customuser_url_argocd_customuser_url_gitea_and_more'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='url_mattermost',
field=models.URLField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='url_nexus',
field=models.URLField(blank=True, null=True),
),
]

View File

@ -5,16 +5,30 @@ from cryptography.fernet import Fernet
class CustomUser(AbstractUser):
"""사용자 모델 - 기존 필드 + SSH Private Key 관리 필드"""
# 기존 필드 유지
# 사용자 모델 - 기존 필드 + SSH Private Key 관리 필드
grade = models.CharField(max_length=50, blank=True, null=True)
nhnc_id = models.CharField(max_length=100, blank=True, null=True)
nhnc_api_tenant_id = models.CharField(max_length=100, blank=True, null=True)
"""사용자 모델 - SSH Private Key 관리 필드"""
# 사용자 모델 - SSH Private Key 관리 필드
encrypted_private_key = models.BinaryField(blank=True, null=True) # 암호화된 SSH 키
# Custom URL 필드 - 2025-01-25
# 여기 추가하면 components/_nav.html 수정
# custom_auth/forms.py 수정, custom_auth/views.py 수정
url_gitea = models.URLField(max_length=200, blank=True, null=True)
url_harbor = models.URLField(max_length=200, blank=True, null=True)
url_argocd = models.URLField(max_length=200, blank=True, null=True)
url_web_ide = models.URLField(max_length=200, blank=True, null=True)
url_rancher = models.URLField(max_length=200, blank=True, null=True)
url_grafana = models.URLField(max_length=200, blank=True, null=True)
url_prometheus = models.URLField(max_length=200, blank=True, null=True)
url_opensearch = models.URLField(max_length=200, blank=True, null=True)
url_kiali = models.URLField(max_length=200, blank=True, null=True)
url_nexus = models.URLField(max_length=200, blank=True, null=True)
url_mattermost = models.URLField(max_length=200, blank=True, null=True)
def encrypt_private_key(self, private_key: str) -> bytes:
"""SSH Private Key 암호화"""
cipher = Fernet(self.get_encryption_key())

View File

@ -1 +1 @@
dev_0.0.23
dev_0.0.24