From 09e904cde590b72185da803363d4bf1828c6f893 Mon Sep 17 00:00:00 2001 From: Steve Kueng <> Date: Thu, 31 Aug 2023 16:47:27 +0200 Subject: [PATCH] removed old functions --- README.md | 8 - api/urls.py | 6 - api/views.py | 46 --- docker/run.sh | 2 +- munkiwebadmin/processor.py | 6 +- munkiwebadmin/templates/base.html | 8 - munkiwebadmin/urls.py | 3 - updates/__init__.py | 0 updates/admin.py | 3 - updates/models.py | 9 - updates/static/updates/js/updates.js | 344 ----------------------- updates/templates/updates/updates.html | 153 ---------- updates/templatetags/__init__.py | 0 updates/templatetags/update_extras.py | 19 -- updates/tests.py | 3 - updates/urls.py | 11 - updates/views.py | 375 ------------------------- 17 files changed, 2 insertions(+), 994 deletions(-) delete mode 100644 updates/__init__.py delete mode 100644 updates/admin.py delete mode 100644 updates/models.py delete mode 100644 updates/static/updates/js/updates.js delete mode 100644 updates/templates/updates/updates.html delete mode 100755 updates/templatetags/__init__.py delete mode 100755 updates/templatetags/update_extras.py delete mode 100644 updates/tests.py delete mode 100644 updates/urls.py delete mode 100644 updates/views.py diff --git a/README.md b/README.md index 8635222d..348e0e8f 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,6 @@ exit #### munkireport scripts [report scripts](https://github.com/SteveKueng/mwa2_scripts) -## Munkiwebadmin with reposado -```bash -docker run --name reposado -d -p 8088:8088 -v Reposado:/reposado mscottblake/reposado -docker run -d -p 8000:80 --name munkiwebadmin -v /Users/Shared/munkirepo:/munkirepo -v Reposado:/reposado -h $HOSTNAME --link postgres_db stevekueng/munkiwebadmin -``` - - ## Munkiwebadmin custom style create a local folder for your styles: ```bash @@ -70,7 +63,6 @@ docker run -d -p 8000:80 --name munkiwebadmin -v /Users/Shared/munkirepo:/munkir | Variable | Usage | Default| | ------------- |-------------|:------:| | APPNAME | Django app name | _MunkiWebAdmin_ | -| SIMPLEMDMKEY | simpleMDM API key. Needed for use with simpleMDM || | ALLOWED_HOSTS | django allowed hosts. e.g. _[ munkiwebadmin.example.com ]_ |_[ * ]_| | DEFAULT_MANIFEST | default manifest to use. _serail_number_ or _hostname_ |_serial_number_ | | PROXY_ADDRESS | proxy server address || diff --git a/api/urls.py b/api/urls.py index b1bc1b2e..bec7baf4 100755 --- a/api/urls.py +++ b/api/urls.py @@ -14,12 +14,6 @@ url(r'^(?Ppkgs)/(?P.*$)', api.views.file_api), url(r'^(?Pvault)/(?P[a-zA-Z]+$)', api.views.db_api), url(r'^(?Pvault)/(?P[a-zA-Z]+)/(?P[a-zA-Z0-9]+$)', api.views.db_api), - url(r'^(?Pupdates$)', api.views.updates_api), - url(r'^(?Pupdates)/(?P.*$)', api.views.updates_api), - url(r'^(?Pmdm)(?:/(?P.[a-zA-Z_]+))(?:/(?P[a-zA-Z0-9]+))(?:/(?P[a-zA-Z_]+))(?:/(?P[a-zA-Z0-9]+))?', api.views.mdm_api), - url(r'^(?Pmdm)(?:/(?P.[a-zA-Z_]+))(?:/(?P[a-zA-Z0-9]+))(?:/(?P[a-zA-Z_]+))?', api.views.mdm_api), - url(r'^(?Pmdm)(?:/(?P.[a-zA-Z_]+))(?:/(?P[a-zA-Z0-9]+))?', api.views.mdm_api), - url(r'^(?Pmdm)(?:/(?P[a-zA-Z_]+))?', api.views.mdm_api), url(r'^(?Psanta)(?:/(?P[a-zA-Z]+))(?:/(?P[a-zA-Z0-9]+))?', api.views.santa_api), url(r'^(?Pinventory)/(?P[a-zA-Z0-9]+$)', api.views.db_api), url(r'^(?P[a-zA-Z]+$)', api.views.db_api), diff --git a/api/views.py b/api/views.py index e2118e13..9542c944 100755 --- a/api/views.py +++ b/api/views.py @@ -38,10 +38,6 @@ import requests from multiprocessing.pool import ThreadPool -if os.listdir('/reposado') != []: - sys.path.append('/reposado/code') - from reposadolib import reposadocommon - LOGGER = logging.getLogger('munkiwebadmin') try: @@ -1126,48 +1122,6 @@ def mdm_api(request, kind, submission_type, primary_id=None, action=None, second # ----------- error 404 ----------------- return HttpResponse(status=404) -@csrf_exempt -@logged_in_or_basicauth() -def updates_api(request, kind, update_id=None): - LOGGER.debug("Got API request for %s" % (kind)) - if os.listdir('/reposado') == []: - return HttpResponse(status=404) - if kind not in ['updates']: - return HttpResponse(status=404) - if not request.user.has_perm('updates.view_updates'): - raise PermissionDenied - - products = reposadocommon.getProductInfo() - catalog_branches = reposadocommon.getCatalogBranches() - - list_of_productids = None - if update_id: - list_of_productids = [update_id] - else: - list_of_productids = products.keys() - - updates = [] - list_of_productids.sort() - for key in list_of_productids: - if products.get(key): - if not catalog_branches: - branchlist = '' - else: - branchlist = [branch for branch in catalog_branches.keys() - if key in catalog_branches[branch]] - branchlist.sort() - - deprecation_state = False - if not products[key].get('AppleCatalogs'): - # not in any Apple catalogs - deprecation_state = True - products[key]['deprecation_state'] = deprecation_state - products[key]['branchlist'] = branchlist - products[key]['id'] = key - updates.append(products[key]) - return HttpResponse(json.dumps(updates, sort_keys=True, indent=1, cls=DjangoJSONEncoder), - content_type='application/json') - @csrf_exempt @logged_in_or_basicauth() def santa_api(request, kind, submission_type, machine_id): diff --git a/docker/run.sh b/docker/run.sh index 78a05cf8..c1ee438a 100644 --- a/docker/run.sh +++ b/docker/run.sh @@ -22,7 +22,7 @@ python manage.py collectstatic --noinput cp static_root/styles/$STYLE/favicon.ico . #update database -python manage.py makemigrations manifests pkgsinfo process reports updates vault +python manage.py makemigrations manifests pkgsinfo process reports vault python manage.py migrate --noinput #chown -R www-data:www-data $APP_DIR diff --git a/munkiwebadmin/processor.py b/munkiwebadmin/processor.py index c194fcbc..65c23a57 100644 --- a/munkiwebadmin/processor.py +++ b/munkiwebadmin/processor.py @@ -30,10 +30,6 @@ except: HOSTNAME = "localhost" -REPOSADO = False -if os.listdir('/reposado') != []: - REPOSADO = True - def index(request): try: image = request.user.ldap_user.attrs["thumbnailPhoto"] @@ -42,5 +38,5 @@ def index(request): imgString = static('img/placeholder.jpg') pass - return {'style': STYLE, 'APPNAME': APPNAME, 'REPOSADO': REPOSADO, 'HOSTNAME': HOSTNAME, 'userImage': imgString } + return {'style': STYLE, 'APPNAME': APPNAME, 'HOSTNAME': HOSTNAME, 'userImage': imgString } diff --git a/munkiwebadmin/templates/base.html b/munkiwebadmin/templates/base.html index b2dca404..8f8e3fcf 100755 --- a/munkiwebadmin/templates/base.html +++ b/munkiwebadmin/templates/base.html @@ -161,14 +161,6 @@

{{APPNAME}}

{% endif %} - {% if REPOSADO and perms.updates.view_updates %} -
  • - - - Updates - -
  • - {% endif %} {% endblock %} diff --git a/munkiwebadmin/urls.py b/munkiwebadmin/urls.py index 46a8491d..d2e35906 100644 --- a/munkiwebadmin/urls.py +++ b/munkiwebadmin/urls.py @@ -30,9 +30,6 @@ url(r'^$', RedirectView.as_view(url='/reports/')), ] -if os.listdir('/reposado') != []: - urlpatterns += [url(r'^updates/', include('updates.urls'))] - # comment out the following if you are serving # static files a different way urlpatterns += staticfiles_urlpatterns() diff --git a/updates/__init__.py b/updates/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/updates/admin.py b/updates/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/updates/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/updates/models.py b/updates/models.py deleted file mode 100644 index a7ed7100..00000000 --- a/updates/models.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.db import models - -class Updates(models.Model): - '''Placeholder so we get permissions entries in the admin database''' - class Meta: - permissions = ( - ('view_updates', 'View updates'), - ) - pass diff --git a/updates/static/updates/js/updates.js b/updates/static/updates/js/updates.js deleted file mode 100644 index ec7fe277..00000000 --- a/updates/static/updates/js/updates.js +++ /dev/null @@ -1,344 +0,0 @@ - -$.ajaxSetup({ - beforeSend: function(xhr, settings) { - if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') { - function getCookie(name) { - var cookieValue = null; - if (document.cookie && document.cookie != '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) == (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - } - if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) { - // Only send the token to relative URLs i.e. locally. - xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); - } - } - } -}); - -$(document).ready(function() { - initUpdatesTable(); - fixDropdown(); - - $('#list_items').on( 'change', 'input.cbox', function () { - element = $(this).attr('id').split(':') - id = new Array(); - id[0] = element[0] - branch = element[1] - if ($(this).prop("checked")) { - addProductToBranch(id, branch); - } else { - removeProductFromBranch(id, branch); - } - } ); -}); - -function fixDropdown() { - // hold onto the drop down menu - var dropdownMenu; - - // and when you show it, move it to the body - $('#page-wrapper').on('show.bs.dropdown', function(e) { - - // grab the menu - dropdownMenu = $(e.target).find('.dropdown-menu'); - - // detach it and append it to the body - $('body').append(dropdownMenu.detach()); - - // grab the new offset position - var eOffset = $(e.target).offset(); - if(eOffset.left + dropdownMenu.width() + 5 > $(window).width()) { - var offsetLeft = $(window).width() - dropdownMenu.width() - 5; - } else { - var offsetLeft = eOffset.left - } - // make sure to place it where it would normally go (this could be improved) - dropdownMenu.css({ - 'display': 'block', - 'top': eOffset.top + $(e.target).outerHeight(), - 'left': offsetLeft - }); - }); - - // and when you hide it, reattach the drop down, and hide it normally - $(window).on('hide.bs.dropdown', function(e) { - $(e.target).append(dropdownMenu.detach()); - dropdownMenu.hide(); - }); -} - -// --- -function initUpdatesTable() { - // start our monitoring timer loop - monitor_update_list(); - var columns = dataTableCols('.table-header'); - var table = $('#list_items').DataTable({ - ajax: { - url: "/updates/", - cache: false, - dataSrc: function ( json ) { - var column_rows = []; - for ( var i=0 ; i < json.length; i++ ) { - if (json[i] != "") { - column_rows.push(json[i]); - } - } - //console.log(column_rows); - return column_rows; - }, - complete: function(jqXHR, textStatus) { - window.clearInterval(poll_loop); - $('#process_progress').modal('hide'); - }, - global: false, - }, - "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { - if ( aData['depricated']) - { - $('td', nRow).addClass('warning'); - } - }, - "columns": columns, - columnDefs: [ - { targets: [0, 1, 2], "orderable": true }, - { targets: [0], "className": 'details-control', "width": "auto" }, - { targets: [1], "width": 50, "className": "left" }, - { targets: [2], "width": 75 }, - { "className": "text-center", "width": 20, "targets": "_all", "orderable": false}, - { targets: [-1], visible: false } - ], - "sDom": "", - "bPaginate": false, - "scrollY": '100%', - drawCallback: function () { // this gets rid of duplicate headers - $('.dataTables_scrollBody thead tr').css({ display: 'none' }); - }, - //"bScrollCollapse": true, - "bInfo": false, - "bFilter": true, - "bStateSave": false, - "aaSorting": [[2,'desc']] - }); - // tie our search field to the table - var thisTable = $('#list_items').DataTable(); - $('#listSearchField').keyup(function(){ - thisTable.search($(this).val()).draw(); - }); - - // Add event listener for opening and closing details - $('#list_items tbody').on('click', 'td.details-control', function () { - var tr = $(this).closest('tr'); - var row = table.row( tr ); - - if ( row.child.isShown() ) { - // This row is already open - close it - row.child.hide(); - tr.removeClass('shown'); - } - else { - // Open this row - row.child( format(row.data()) ).show(); - tr.addClass('shown'); - } - } ); -} - -function monitor_update_list() { - $('#process_progress_title_text').text('Getting updates...') - $('#process_progress_status_text').text('Processing...') - poll_loop = setInterval(function() { - update_status('/updates/__get_update_list_status'); - }, 200); -} - -function dataTableCols(id) { - keylist = ['key', 'title', 'version', 'date', 'depricated'] - columns = $(id).map(function() { - item = { "data": $(this).attr('id') }; - return item - }).get();; - return columns -} - -/* Formatting function for row details - modify as you need */ -function format( d ) { - // `d` is the original data object for the row - return '' + d.key + '

    ' + d.description -} - -function filterDatatable(filter) { - clearFilterDatatable() - $.fn.dataTableExt.afnFiltering.push( - function( oSettings, aData, iDataIndex, rowData, counter ) { - switch(filter) { - case "depricated": - return JSON.parse(aData[aData.length - 1]) - break; - case "no-depricated": - return !JSON.parse(aData[aData.length - 1]) - break; - } - } - ); - $('#list_items').dataTable().fnDraw(); // Manually redraw the table after filtering -} - -function clearFilterDatatable() { - $.fn.dataTableExt.afnFiltering.length = 0; - $('#list_items').dataTable().fnDraw(); -} - -// add new branch -function newBranch(branch) { - if(branch != "") { - $.ajax({ - url: '/updates/new_branch/'+branch, - type: 'POST', - contentType: 'application/json; charset=utf-8', - success: function() { - location.reload(); - }, - error: function(jqXHR, textStatus, errorThrown) { - $("#errorModalTitleText").text("create branch error"); - try { - var json_data = $.parseJSON(jqXHR.responseText) - if (json_data['result'] == 'failed') { - $("#errorModalDetailText").text(json_data['detail']); - $("#errorModal").modal("show"); - return; - } - } catch(err) { - // do nothing - } - $("#errorModalDetailText").text(errorThrown); - $("#errorModal").modal("show"); - } - }); - } -} - -function deleteBranch(branch) { - if(branch != "") { - $.ajax({ - url: '/updates/delete_branch/'+branch, - type: 'POST', - contentType: 'application/json; charset=utf-8', - success: function() { - location.reload(); - }, - error: function(jqXHR, textStatus, errorThrown) { - $("#errorModalTitleText").text("delete branch error"); - try { - var json_data = $.parseJSON(jqXHR.responseText) - if (json_data['result'] == 'failed') { - $("#errorModalDetailText").text(json_data['detail']); - $("#errorModal").modal("show"); - return; - } - } catch(err) { - // do nothing - } - $("#errorModalDetailText").text(errorThrown); - $("#errorModal").modal("show"); - } - }); - } -} - -function openDeleteBranchConfirmModal(branch) { - $('#confirmationModalTitle').text("Delete selected branch?"); - $('#confirmationModalBodyText').html("Really delete "+branch+"?
    This action cannot be undone."); - $('#confirmationButton').attr("onclick","deleteBranch('"+branch+"')"); - $('#confirmationButton').text("Delete"); - $('#confirmationModal').modal({ - show: 'true', - }); -} - -function openAddProductConfirmModal(branch, products) { - $('#confirmationModalTitle').text("Add products to branch?"); - $('#confirmationModalBodyText').html("Really add "+products+" to "+branch+"?"); - $('#confirmationButton').attr("onclick","addProductToBranch(['"+products+"'], '"+branch+"', true)"); - $('#confirmationButton').text("Add"); - $('#confirmationModal').modal({ - show: 'true', - }); -} - -function openRemoveProductConfirmModal(branch, products) { - $('#confirmationModalTitle').text("Remove products from branch?"); - $('#confirmationModalBodyText').html("Really remove "+products+" from "+branch+"?"); - $('#confirmationButton').attr("onclick","removeProductFromBranch(['"+products+"'], '"+branch+"', true)"); - $('#confirmationButton').text("Remove"); - $('#confirmationModal').modal({ - show: 'true', - }); -} - -function addProductToBranch(products, branch, reload = false) { - $.ajax({ - url: '/updates/add_product', - type: 'POST', - data: {product_id_list: products, branch_name: branch}, - dataType: 'json', - success: function() { - if(reload) { - location.reload(); - } - }, - error: function(jqXHR, textStatus, errorThrown) { - $("#errorModalTitleText").text("product add error"); - try { - var json_data = $.parseJSON(jqXHR.responseText) - if (json_data['result'] == 'failed') { - $("#errorModalDetailText").text(json_data['detail']); - $("#errorModal").modal("show"); - return; - } - } catch(err) { - // do nothing - } - $("#errorModalDetailText").text(errorThrown); - $("#errorModal").modal("show"); - }, - }); -} - -function removeProductFromBranch(products, branch, reload = false) { - $.ajax({ - url: '/updates/remove_product', - type: 'POST', - data: {product_id_list: products, branch_name: branch}, - dataType: 'json', - success: function() { - if(reload) { - location.reload(); - } - }, - error: function(jqXHR, textStatus, errorThrown) { - $("#errorModalTitleText").text("product remove error"); - try { - var json_data = $.parseJSON(jqXHR.responseText) - if (json_data['result'] == 'failed') { - $("#errorModalDetailText").text(json_data['detail']); - $("#errorModal").modal("show"); - return; - } - } catch(err) { - // do nothing - } - $("#errorModalDetailText").text(errorThrown); - $("#errorModal").modal("show"); - } - }); -} \ No newline at end of file diff --git a/updates/templates/updates/updates.html b/updates/templates/updates/updates.html deleted file mode 100644 index d4024a51..00000000 --- a/updates/templates/updates/updates.html +++ /dev/null @@ -1,153 +0,0 @@ -{% extends "base.html" %} -{% load static %} - -{% block java_script %} - - -{% endblock %} - -{% block content %} -
    -
    -
    -
    -
    -
    - - -
    - {% if perms.manifests.add_manifestfile %} -
    - -
    - {% endif %} -
    - -
    - - - - - - - - {% for branch in branches %} - - {% endfor %} - - - - - - -
    TitleVersionDateDepricated
    -
    -
    -
    - - - - - - - - - -{% endblock %} \ No newline at end of file diff --git a/updates/templatetags/__init__.py b/updates/templatetags/__init__.py deleted file mode 100755 index e69de29b..00000000 diff --git a/updates/templatetags/update_extras.py b/updates/templatetags/update_extras.py deleted file mode 100755 index 17fbf421..00000000 --- a/updates/templatetags/update_extras.py +++ /dev/null @@ -1,19 +0,0 @@ -from django import template - -register = template.Library() - -@register.filter -def humanreadablesize(bytes): - """Returns sizes in human-readable units. Input is bytes""" - try: - bytes = float(bytes) - except (TypeError, ValueError, UnicodeDecodeError): - return "unknown" - - units = [(" B", 2**10), (" KB", 2**20), (" MB", 2**30), (" GB", 2**40), (" TB", 2**50)] - for suffix, limit in units: - if bytes > limit: - continue - else: - return str(round(bytes/float(limit/2**10), 1)) + suffix -humanreadablesize.is_safe = True \ No newline at end of file diff --git a/updates/tests.py b/updates/tests.py deleted file mode 100644 index 7ce503c2..00000000 --- a/updates/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/updates/urls.py b/updates/urls.py deleted file mode 100644 index cc232c36..00000000 --- a/updates/urls.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.conf.urls import url -import updates.views - -urlpatterns = [ - url(r'^add_product$', updates.views.add_product_to_branch), - url(r'^remove_product$', updates.views.remove_product_from_branch), - url(r'^delete_branch/(?P.*$)', updates.views.delete_branch), - url(r'^new_branch/(?P.*$)', updates.views.new_branch), - url(r'^__get_update_list_status$', updates.views.status), - url(r'^$', updates.views.index, name='updates'), -] \ No newline at end of file diff --git a/updates/views.py b/updates/views.py deleted file mode 100644 index 1852d64a..00000000 --- a/updates/views.py +++ /dev/null @@ -1,375 +0,0 @@ -from django.shortcuts import get_object_or_404, redirect, render -from django.http import HttpResponse -from django.contrib.auth.decorators import login_required, permission_required -from django.conf import settings -from process.models import Process - -import json -import os -import logging -import re -import sys - -from operator import itemgetter - -try: - BASE_DIR = settings.BASE_DIR -except: - BASE_DIR = "" - -if os.listdir('/reposado') != []: - sys.path.append('/reposado/code') - from reposadolib import reposadocommon - -LOGGER = logging.getLogger('munkiwebadmin') - -def prefsFilePath(): - return os.path.join('/reposado/code', 'preferences.plist') - -reposadocommon.prefsFilePath = prefsFilePath - -@login_required -def status(request): - '''Returns status of long-running process''' - LOGGER.debug('got status request for update_list_process') - status_response = {} - processes = Process.objects.filter(name='update_list_process') - if processes: - # display status from one of the active processes - # (hopefully there is only one!) - process = processes[0] - status_response['statustext'] = process.statustext - else: - status_response['statustext'] = 'Processing' - return HttpResponse(json.dumps(status_response), - content_type='application/json') - -def list_products(sort_order='date'): - '''Prints a list of Software Update products''' - - def sort_by_key(a, b): - """Internal comparison function for use with sorting""" - return cmp(a['sort_key'], b['sort_key']) - - sort_keys = {'date': 'PostDate', - 'title': 'title', - 'id': 'id'} - - sort_key = sort_keys.get(sort_order, 'PostDate') - errormessages = [] - products = reposadocommon.getProductInfo() - catalog_branches = reposadocommon.getCatalogBranches() - product_list = [] - list_of_productids = products.keys() - for productid in list_of_productids: - if not productid in products: - errormessages.append( - 'Skipped product %s because it does not exist ' - 'in the ProductInfo database.' % productid) - continue - product_dict = {} - product_dict['key'] = productid - if sort_key == 'id': - product_dict['sort_key'] = productid - else: - try: - product_dict['sort_key'] = products[productid][sort_key] - except KeyError: - errormessages.append( - 'Product %s is missing the sort key %s -- ' - 'Product info database may be incomplete' - % (productid, sort_key)) - continue - product_list.append(product_dict) - product_list.sort(sort_by_key) - product_item = [] - for product in product_list: - if product['key'] in products: - deprecation_state = False - if not products[product['key']].get('AppleCatalogs'): - # not in any Apple catalogs - deprecation_state = True - try: - post_date = products[product['key']].get('PostDate').strftime('%Y-%m-%d') - except BaseException: - post_date = 'None' - - if products[product['key']].get('description', 'None'): - description = re.findall('(.*?)', products[product['key']].get('description'), re.DOTALL) - - item = {'key': product['key'], - 'title': products[product['key']].get('title'), - 'version': products[product['key']].get('version'), - 'date': post_date, - 'depricated': deprecation_state, - 'description': description - } - - if catalog_branches: - for branch in catalog_branches.keys(): - if product['key'] in catalog_branches[branch]: - item[branch] = '' - else: - item[branch] = '' - - product_item.append(item) - return product_item - -@login_required -@permission_required('updates.view_updates', login_url='/login/') -def index(request): - if request.is_ajax(): - response = list_products() - return HttpResponse(json.dumps(response), - content_type='application/json') - - try: - catalog_branches = reposadocommon.getCatalogBranches().keys() - except: - catalog_branches = [] - context = {'branches': sorted(catalog_branches)} - return render(request, 'updates/updates.html', context=context) - -@login_required -@permission_required('updates.add_updates', login_url='/login/') -def new_branch(request, branchname): - catalog_branches = reposadocommon.getCatalogBranches() - if branchname in catalog_branches: - return HttpResponse( - json.dumps({'result': 'failed', - 'exception_type': 'Branch already exists!', - 'detail': 'Branch already exists!'}), - content_type='application/json', status=404) - catalog_branches[branchname] = [] - reposadocommon.writeCatalogBranches(catalog_branches) - return HttpResponse("OK") - -@login_required -@permission_required('updates.delete_updates', login_url='/login/') -def delete_branch(request, branchname): - catalog_branches = reposadocommon.getCatalogBranches() - if not branchname in catalog_branches: - reposadocommon.print_stderr('Branch %s does not exist!', branchname) - return - - del catalog_branches[branchname] - - # this is not in the common library, so we have to duplicate code - # from repoutil - for catalog_URL in reposadocommon.pref('AppleCatalogURLs'): - localcatalogpath = reposadocommon.getLocalPathNameFromURL(catalog_URL) - # now strip the '.sucatalog' bit from the name - if localcatalogpath.endswith('.sucatalog'): - localcatalogpath = localcatalogpath[0:-10] - branchcatalogpath = localcatalogpath + '_' + branchname + '.sucatalog' - if os.path.exists(branchcatalogpath): - reposadocommon.print_stdout( - 'Removing %s', os.path.basename(branchcatalogpath)) - os.remove(branchcatalogpath) - - reposadocommon.writeCatalogBranches(catalog_branches) - - return HttpResponse("OK") - -@login_required -@permission_required('updates.change_updates', login_url='/login/') -def add_all(request, branchname): - products = reposadocommon.getProductInfo() - catalog_branches = reposadocommon.getCatalogBranches() - - catalog_branches[branchname] = products.keys() - - reposadocommon.writeCatalogBranches(catalog_branches) - reposadocommon.writeAllBranchCatalogs() - - return HttpResponse("OK") - -@login_required -@permission_required('updates.change_updates', login_url='/login/') -def add_product_to_branch(request): - '''Adds one product to a branch. Takes a list of strings. - The last string must be the name of a branch catalog. All other - strings must be product_ids.''' - if request.is_ajax(): - branch_name = request.POST.get('branch_name') - product_id_list = request.POST.getlist('product_id_list[]') - - # remove all duplicate product ids - product_id_list = list(set(product_id_list)) - - catalog_branches = reposadocommon.getCatalogBranches() - if not branch_name in catalog_branches: - return HttpResponse(json.dumps({'result': 'failed', - 'exception_type': 'Catalog branch not found', - 'detail': 'Catalog branch '+branch_name+' doesn\'t exist!'}), - content_type='application/json', status=500) - - products = reposadocommon.getProductInfo() - if 'all' in product_id_list: - product_id_list = products.keys() - elif 'non-deprecated' in product_id_list: - product_id_list = [key for key in products.keys() - if products[key].get('AppleCatalogs')] - - for product_id in product_id_list: - if not product_id in products: - return HttpResponse(json.dumps({'result': 'failed', - 'exception_type': 'Product not found', - 'detail': 'Product '+product_id+' doesn\'t exist!'}), - content_type='application/json', status=500) - else: - try: - title = products[product_id]['title'] - vers = products[product_id]['version'] - except KeyError: - # skip this one and move on - continue - if product_id in catalog_branches[branch_name]: - reposadocommon.print_stderr( - '%s (%s-%s) is already in branch %s!', - product_id, title, vers, branch_name) - continue - else: - catalog_branches[branch_name].append(product_id) - - reposadocommon.writeCatalogBranches(catalog_branches) - reposadocommon.writeAllBranchCatalogs() - return HttpResponse(status=204) - -@login_required -@permission_required('updates.change_updates', login_url='/login/') -def remove_product_from_branch(request): - '''Removes one or more products from a branch. Takes a list of strings. - The last string must be the name of a branch catalog. All other - strings must be product_ids.''' - if request.is_ajax(): - branch_name = request.POST.get('branch_name') - product_id_list = request.POST.getlist('product_id_list[]') - - catalog_branches = reposadocommon.getCatalogBranches() - if not branch_name in catalog_branches: - return HttpResponse(json.dumps({'result': 'failed', - 'exception_type': 'Catalog branch not found', - 'detail': 'Catalog branch '+branch_name+' doesn\'t exist!'}), - content_type='application/json', status=500) - - products = reposadocommon.getProductInfo() - if 'all' in product_id_list: - product_id_list = products.keys() - elif 'deprecated' in product_id_list: - product_id_list = [key for key in catalog_branches[branch_name] - if not products[key].get('AppleCatalogs')] - else: - # remove all duplicate product ids - product_id_list = list(set(product_id_list)) - - for product_id in product_id_list: - if product_id in products: - title = products[product_id].get('title') - vers = products[product_id].get('version') - else: - return HttpResponse(json.dumps({'result': 'failed', - 'exception_type': 'Product not found', - 'detail': 'Product '+product_id+' doesn\'t exist!'}), - content_type='application/json', status=500) - if not product_id in catalog_branches[branch_name]: - reposadocommon.print_stderr('%s (%s-%s) is not in branch %s!', - product_id, title, vers, branch_name) - continue - - catalog_branches[branch_name].remove(product_id) - reposadocommon.writeCatalogBranches(catalog_branches) - reposadocommon.writeAllBranchCatalogs() - return HttpResponse(status=204) - -@login_required -@permission_required('updates.delete_updates', login_url='/login/') -def purge_product(request, product_ids="all-deprecated", force=False): - '''Removes products from the ProductInfo.plist and purges their local - replicas (if they exist). Warns and skips if a product is not deprecated - or is in any branch, unless force == True. If force == True, product is - also removed from all branches. This action is destructive and cannot be - undone. - product_ids is a list of productids.''' - - # sanity checking - for item in product_ids: - if item.startswith('-'): - reposadocommon.print_stderr('Ambiguous parameters: can\'t tell if ' - '%s is a parameter or an option!', item) - return - - products = reposadocommon.getProductInfo() - catalog_branches = reposadocommon.getCatalogBranches() - downloaded_product_list = reposadocommon.getDownloadStatus() - - if 'all-deprecated' in product_ids: - product_ids.remove('all-deprecated') - deprecated_productids = [key for key in products.keys() - if not products[key].get('AppleCatalogs')] - product_ids.extend(deprecated_productids) - - # remove all duplicate product ids - product_ids = list(set(product_ids)) - - for product_id in product_ids: - if not product_id in products: - reposadocommon.print_stderr( - 'Product %s does not exist in the ProductInfo database. ' - 'Skipping.', product_id) - continue - product = products[product_id] - product_short_info = ('%s (%s-%s)' - % (product_id, product.get('title'), product.get('version'))) - if product.get('AppleCatalogs') and not force: - reposadocommon.print_stderr( - 'WARNING: Product %s is in Apple catalogs:\n %s', - product_short_info, '\n '.join(product['AppleCatalogs'])) - reposadocommon.print_stderr('Skipping product %s', product_id) - continue - branches_with_product = [branch for branch in catalog_branches.keys() - if product_id in catalog_branches[branch]] - if branches_with_product: - if not force: - reposadocommon.print_stderr( - 'WARNING: Product %s is in catalog branches:\n %s', - product_short_info, '\n '.join(branches_with_product)) - reposadocommon.print_stderr('Skipping product %s', product_id) - continue - else: - # remove product from all branches - for branch_name in branches_with_product: - reposadocommon.print_stdout( - 'Removing %s from branch %s...', - product_short_info, branch_name) - catalog_branches[branch_name].remove(product_id) - - local_copy = getProductLocation(product, product_id) - if local_copy: - # remove local replica - reposadocommon.print_stdout( - 'Removing replicated %s from %s...', - product_short_info, local_copy) - try: - shutil.rmtree(local_copy) - except (OSError, IOError), err: - reposadocommon.print_stderr( - 'Error: %s', err) - # but not fatal, so keep going... - # delete product from ProductInfo database - del products[product_id] - # delete product from downloaded product list - if product_id in downloaded_product_list: - downloaded_product_list.remove(product_id) - - # write out changed catalog branches, productInfo, - # and rebuild our local and branch catalogs - reposadocommon.writeDownloadStatus(downloaded_product_list) - reposadocommon.writeCatalogBranches(catalog_branches) - reposadocommon.writeProductInfo(products) - reposadocommon.writeAllLocalCatalogs() - - return HttpResponse("OK") - - -