views.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. from django.shortcuts import render, redirect, get_object_or_404
  2. from django.contrib.auth.decorators import login_required
  3. from django.contrib.auth import login, logout
  4. from django.contrib.auth.forms import AuthenticationForm
  5. from django.contrib import messages
  6. from django.http import JsonResponse
  7. from .models import RegistryConfig
  8. from .forms import RegistryConfigForm
  9. from .registry_client import RegistryClient
  10. def login_view(request):
  11. if request.user.is_authenticated:
  12. return redirect('dashboard')
  13. if request.method == 'POST':
  14. form = AuthenticationForm(request, data=request.POST)
  15. if form.is_valid():
  16. user = form.get_user()
  17. login(request, user)
  18. messages.success(request, f'Bienvenido {user.username}')
  19. return redirect('dashboard')
  20. else:
  21. form = AuthenticationForm()
  22. return render(request, 'explorer/login.html', {'form': form})
  23. def logout_view(request):
  24. logout(request)
  25. messages.info(request, 'Sesión cerrada')
  26. return redirect('login')
  27. @login_required
  28. def dashboard(request):
  29. registries = RegistryConfig.objects.all()
  30. return render(request, 'explorer/dashboard.html', {'registries': registries})
  31. @login_required
  32. def registry_create(request):
  33. if request.method == 'POST':
  34. form = RegistryConfigForm(request.POST)
  35. if form.is_valid():
  36. config = form.save(commit=False)
  37. client = RegistryClient(
  38. url=config.url,
  39. username=config.username,
  40. password=config.password,
  41. verify_ssl=config.verify_ssl
  42. )
  43. ok, msg = client.check_connection()
  44. if ok:
  45. config.save()
  46. messages.success(request, f'Registry "{config.name}" configurado correctamente')
  47. return redirect('dashboard')
  48. else:
  49. messages.error(request, f'No se pudo conectar: {msg}')
  50. else:
  51. form = RegistryConfigForm()
  52. return render(request, 'explorer/registry_form.html', {'form': form, 'title': 'Agregar Registry'})
  53. @login_required
  54. def registry_edit(request, pk):
  55. config = get_object_or_404(RegistryConfig, pk=pk)
  56. if request.method == 'POST':
  57. form = RegistryConfigForm(request.POST, instance=config)
  58. if form.is_valid():
  59. form.save()
  60. messages.success(request, f'Registry "{config.name}" actualizado')
  61. return redirect('dashboard')
  62. else:
  63. form = RegistryConfigForm(instance=config)
  64. return render(request, 'explorer/registry_form.html', {'form': form, 'title': 'Editar Registry'})
  65. @login_required
  66. def registry_delete(request, pk):
  67. config = get_object_or_404(RegistryConfig, pk=pk)
  68. if request.method == 'POST':
  69. name = config.name
  70. config.delete()
  71. messages.success(request, f'Registry "{name}" eliminado')
  72. return redirect('dashboard')
  73. return render(request, 'explorer/registry_confirm_delete.html', {'config': config})
  74. @login_required
  75. def registry_repositories(request, pk):
  76. config = get_object_or_404(RegistryConfig, pk=pk)
  77. client = RegistryClient(
  78. url=config.url,
  79. username=config.username,
  80. password=config.password,
  81. verify_ssl=config.verify_ssl
  82. )
  83. ok, msg = client.check_connection()
  84. if not ok:
  85. messages.error(request, f'Error de conexión: {msg}')
  86. return redirect('dashboard')
  87. try:
  88. repositories = client.list_catalog()
  89. except Exception as e:
  90. messages.error(request, f'Error al listar repositorios: {str(e)}')
  91. repositories = []
  92. search = request.GET.get('search', '').strip()
  93. if search:
  94. repositories = [r for r in repositories if search.lower() in r.lower()]
  95. return render(request, 'explorer/repositories.html', {
  96. 'config': config,
  97. 'repositories': repositories,
  98. 'search': search,
  99. 'count': len(repositories),
  100. })
  101. @login_required
  102. def repository_tags(request, pk, repo_name):
  103. config = get_object_or_404(RegistryConfig, pk=pk)
  104. client = RegistryClient(
  105. url=config.url,
  106. username=config.username,
  107. password=config.password,
  108. verify_ssl=config.verify_ssl
  109. )
  110. try:
  111. tags = client.list_tags(repo_name)
  112. except Exception as e:
  113. messages.error(request, f'Error al listar tags: {str(e)}')
  114. tags = []
  115. search = request.GET.get('search', '').strip()
  116. if search:
  117. tags = [t for t in tags if search.lower() in t.lower()]
  118. return render(request, 'explorer/tags.html', {
  119. 'config': config,
  120. 'repo_name': repo_name,
  121. 'tags': tags,
  122. 'search': search,
  123. 'count': len(tags),
  124. })
  125. @login_required
  126. def image_detail(request, pk, repo_name, tag):
  127. config = get_object_or_404(RegistryConfig, pk=pk)
  128. client = RegistryClient(
  129. url=config.url,
  130. username=config.username,
  131. password=config.password,
  132. verify_ssl=config.verify_ssl
  133. )
  134. try:
  135. detail = client.get_image_detail(repo_name, tag)
  136. except Exception as e:
  137. messages.error(request, f'Error al obtener detalles: {str(e)}')
  138. return redirect('repository_tags', pk=pk, repo_name=repo_name)
  139. return render(request, 'explorer/image_detail.html', {
  140. 'config': config,
  141. 'repo_name': repo_name,
  142. 'tag': tag,
  143. 'detail': detail,
  144. })
  145. @login_required
  146. def image_delete(request, pk, repo_name, tag):
  147. config = get_object_or_404(RegistryConfig, pk=pk)
  148. if request.method != 'POST':
  149. return redirect('image_detail', pk=pk, repo_name=repo_name, tag=tag)
  150. client = RegistryClient(
  151. url=config.url,
  152. username=config.username,
  153. password=config.password,
  154. verify_ssl=config.verify_ssl
  155. )
  156. ok, msg = client.delete_manifest(repo_name, tag)
  157. if ok:
  158. messages.success(request, msg)
  159. else:
  160. messages.error(request, msg)
  161. return redirect('repository_tags', pk=pk, repo_name=repo_name)
  162. @login_required
  163. def api_check_connection(request):
  164. if request.method != 'POST':
  165. return JsonResponse({'error': 'Método no permitido'}, status=405)
  166. url = request.POST.get('url', '')
  167. username = request.POST.get('username', '')
  168. password = request.POST.get('password', '')
  169. verify_ssl = request.POST.get('verify_ssl', 'on') == 'on'
  170. if not url:
  171. return JsonResponse({'ok': False, 'message': 'URL requerida'})
  172. client = RegistryClient(url=url, username=username, password=password, verify_ssl=verify_ssl)
  173. ok, msg = client.check_connection()
  174. return JsonResponse({'ok': ok, 'message': msg})