Changeset - 630bf4086135
[Not reviewed]
11 29 11
Joel Addison - 21 months ago 2022-12-07 14:08:54
joel@addison.net.au
Everything Open 2023 - Initial Setup
47 files changed with 406 insertions and 512 deletions:
0 comments (0 inline, 0 general)
.gitlab-ci.yml
Show inline comments
 
stages:
 
  - build
 
  - deploy
 

	
 
variables:
 
  DOCKER_TLS_CERTDIR: "/certs"
 
  CONTAINER_PREFIX: 2022
 
  CONTAINER_PREFIX: 2023
 
  CONTAINER_IMAGE: $CI_REGISTRY_IMAGE/$CONTAINER_PREFIX:$CI_COMMIT_SHA
 

	
 
build-image:
 
  image: docker:git
 
  stage: build
 
  services:
 
  - docker:dind
 
  script:
 
    - apk update && apk add git
 
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
 
    - docker build --pull -f docker/Dockerfile -t $CONTAINER_IMAGE .
 
    - docker push $CONTAINER_IMAGE
 
  only:
 
    - "2022"
 
    - conf/2023
 

	
 
k8s-deploy-staging:
 
  image: google/cloud-sdk
 
  stage: deploy
 
  script:
 
  - echo "${CA_CERT}" > cert.crt
 
  - kubectl config set-cluster cluster --server="${KUBE_SERVER}" --embed-certs=true --certificate-authority=cert.crt
 
  - kubectl config set-context cluster --cluster=cluster --namespace=lca2022-staging --user=gitlab-ci
 
  - kubectl config set-context cluster --cluster=cluster --namespace=eo2023-staging --user=gitlab-ci
 
  - kubectl config use-context cluster
 
  - kubectl --token "${KUBE_TOKEN}" set image deployment/symposion-app symposion-app=$CONTAINER_IMAGE
 
  when: manual
 
  only:
 
  - dev/2022
 
  - dev/2023
 
  environment:
 
    name: 2022/staging
 
    url: https://staging-lca2022.gc2020.org/
 
    name: 2023/staging
 
    url: https://staging-eo2023.osaconftools.net/
 

	
 
k8s-deploy-prod:
 
  image: google/cloud-sdk
 
  stage: deploy
 
  script:
 
  - echo "${CA_CERT}" > cert.crt
 
  - kubectl config set-cluster cluster --server="${KUBE_SERVER}" --embed-certs=true --certificate-authority=cert.crt
 
  - kubectl config set-context cluster --cluster=cluster --namespace=lca2022-prod --user=gitlab-ci
 
  - kubectl config set-context cluster --cluster=cluster --namespace=eo2023-prod --user=gitlab-ci
 
  - kubectl config use-context cluster
 
  - kubectl --token "${KUBE_TOKEN}" set image deployment/symposion-app symposion-app=$CONTAINER_IMAGE
 
  when: manual
 
  only:
 
  - "2022"
 
  - conf/2023
 
  environment:
 
    name: 2022/prod
 
    url: https://lca2022.linux.org.au
 
    name: 2023/prod
 
    url: https://2023.everythingopen.au/
 

	
 
.docs_template: &sphinx
 
  image: alpine
 
  script:
 
  - apk --no-cache add py3-pip python3-dev make
 
  - pip install sphinx
 
  - cd docs
 
  - make html
 
  - cd ..
 
  - mv docs/_build/html public
 
  artifacts:
 
    paths:
 
    - public
 

	
 
pages:
 
  <<: *sphinx
 
  stage: build
 
  only:
 
  - master
 
  - "2022"
 
  - conf/2023
 
  environment:
 
    name: docs
 
    url: https://laconfdev.gitlab.io/symposion_app/
 

	
 
build-sphinx:
 
  <<: *sphinx
 
  stage: build
 
  except:
 
  - master
 
  - "2022"
 
  - conf/2023
fixtures/2022/auth.permission.json
Show inline comments
 
deleted file
fixtures/2022/conference.section.json
Show inline comments
 
deleted file
fixtures/2022/proposals.proposalsection.json
Show inline comments
 
deleted file
fixtures/conference.json
Show inline comments
 
[
 
{
 
  "model": "symposion_conference.conference",
 
  "pk": 1,
 
  "fields": {
 
    "title": "linux.conf.au 2022",
 
    "start_date": "2022-01-14",
 
    "end_date": "2022-01-16",
 
    "timezone": "Australia/Canberra"
 
    "title": "Everything Open 2023",
 
    "start_date": "2023-03-14",
 
    "end_date": "2023-03-16",
 
    "timezone": "Australia/Melbourne"
 
  }
 
}
 
]
fixtures/flatpages.json
Show inline comments
 
[
 
{
 
  "model": "flatpages.flatpage",
 
  "pk": 1,
 
  "fields": {
 
    "url": "/",
 
    "title": "Home Page",
 
    "content": "Here is the home page for LCA.\r\n\r\nOther pages to come.",
 
    "content": "Here is the home page.\r\n\r\nOther pages to come.",
 
    "enable_comments": false,
 
    "template_name": "",
 
    "registration_required": false,
 
    "sites": [
 
      1
 
    ]
 
  }
 
}
 
]
fixtures/sessions/auth.group.json
Show inline comments
 
file renamed from fixtures/2022/auth.group.json to fixtures/sessions/auth.group.json
fixtures/sessions/auth.permission.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "auth.permission",
 
  "fields": {
 
    "name": "Can review Main Conference",
 
    "content_type": [
 
      "reviews",
 
      ""
 
    ],
 
    "codename": "can_review_main"
 
  }
 
},
 
{
 
  "model": "auth.permission",
 
  "fields": {
 
    "name": "Can manage Main Conference",
 
    "content_type": [
 
      "reviews",
 
      ""
 
    ],
 
    "codename": "can_manage_main"
 
  }
 
}
 
]
fixtures/sessions/conference.section.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "symposion_conference.section",
 
  "pk": 1,
 
  "fields": {
 
    "conference": 1,
 
    "name": "Main Conference",
 
    "slug": "main",
 
    "start_date": "2023-03-14",
 
    "end_date": "2023-03-16"
 
  }
 
}
 
]
fixtures/sessions/proposals.proposalkind.json
Show inline comments
 
file renamed from fixtures/2022/proposals.proposalkind.json to fixtures/sessions/proposals.proposalkind.json
 
[
 
{
 
  "model": "symposion_proposals.proposalkind",
 
  "pk": 1,
 
  "fields": {
 
    "section": 1,
 
    "name": "Talk",
 
    "slug": "talk"
 
  }
 
},
 
{
 
  "model": "symposion_proposals.proposalkind",
 
  "pk": 3,
 
  "pk": 2,
 
  "fields": {
 
    "section": 2,
 
    "name": "Miniconf",
 
    "slug": "miniconf"
 
    "section": 1,
 
    "name": "Tutorial",
 
    "slug": "tutorial"
 
  }
 
}
 
]
fixtures/sessions/proposals.proposalsection.json
Show inline comments
 
new file 100644
 
[
 
{
 
  "model": "symposion_proposals.proposalsection",
 
  "pk": 1,
 
  "fields": {
 
    "section": 1,
 
    "start": "2022-12-07T12:00:00Z",
 
    "end": "2023-01-09T12:00:00Z",
 
    "closed": false,
 
    "published": true
 
  }
 
}
 
]
fixtures/sessions/teams.team.json
Show inline comments
 
file renamed from fixtures/2022/teams.team.json to fixtures/sessions/teams.team.json
 
[
 
{
 
  "model": "teams.team",
 
  "pk": 1,
 
  "fields": {
 
    "slug": "main-proposals",
 
    "name": "linux.conf.au Sessions Team",
 
    "description": "Team looking after the linux.conf.au Call for Sessions",
 
    "name": "Sessions Team",
 
    "description": "Team looking after the Call for Sessions",
 
    "access": "invitation",
 
    "created": "2019-06-23T08:16:34.032Z",
 
    "permissions": [
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_miniconf",
 
        "reviews",
 
        ""
 
      ]
 
    ],
 
    "manager_permissions": [
 
      [
 
        "can_manage_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ]
 
    ]
 
  }
 
},
 
{
 
  "model": "teams.team",
 
  "pk": 2,
 
  "fields": {
 
    "slug": "organising-team",
 
    "name": "linux.conf.au Organising Team",
 
    "description": "The organising team for linux.conf.au",
 
    "name": "Organising Team",
 
    "description": "The conference organising team",
 
    "access": "invitation",
 
    "created": "2019-08-26T22:59:09.265Z",
 
    "permissions": [
 
      [
 
        "can_review_main",
 
        "reviews",
 
        ""
 
      ],
 
      [
 
        "can_review_miniconf",
 
        "reviews",
 
        ""
 
      ]
 
    ],
 
    "manager_permissions": []
 
  }
 
}
 
]
fixtures/sites.json
Show inline comments
 
[
 
{
 
  "model": "sites.site",
 
  "pk": 1,
 
  "fields": {
 
    "domain": "lca2022.linux.org.au",
 
    "name": "linux.conf.au 2022"
 
    "domain": "2023.everythingopen.au",
 
    "name": "Everything Open 2023"
 
  }
 
}
 
]
fixtures/sitetree.json
Show inline comments
 
[
 
{
 
  "model": "sitetree.tree",
 
  "pk": 1,
 
  "fields": {
 
    "title": "main",
 
    "alias": "main"
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 1,
 
  "fields": {
 
    "title": "Home",
 
    "hint": "",
 
    "url": "/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 1,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 2,
 
  "fields": {
 
    "title": "About",
 
    "hint": "",
 
    "url": "#",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 2,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 3,
 
  "fields": {
 
    "title": "Programme",
 
    "hint": "",
 
    "url": "#",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 5,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 4,
 
  "fields": {
 
    "title": "Sponsors",
 
    "hint": "",
 
    "url": "/sponsors/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 8,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 5,
 
  "fields": {
 
    "title": "News",
 
    "hint": "",
 
    "url": "/news/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 3,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 6,
 
  "fields": {
 
    "title": "About LCA2022",
 
    "title": "About Everything Open",
 
    "hint": "",
 
    "url": "/about/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 2,
 
    "sort_order": 6,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 7,
 
  "fields": {
 
    "title": "Location",
 
    "hint": "",
 
    "url": "/about/location/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 2,
 
    "sort_order": 7,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 8,
 
  "fields": {
 
    "title": "Attend",
 
    "hint": "",
 
    "url": "#",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 4,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 9,
 
  "fields": {
 
    "title": "Dashboard",
 
    "hint": "",
 
    "url": "/dashboard",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 8,
 
    "sort_order": 9,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 10,
 
  "fields": {
 
    "title": "Code of Conduct",
 
    "hint": "",
 
    "url": "/attend/code-of-conduct/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 8,
 
    "sort_order": 22,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 11,
 
  "fields": {
 
    "title": "Terms and Conditions",
 
    "hint": "",
 
    "url": "/attend/terms-and-conditions/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 8,
 
    "sort_order": 23,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 12,
 
  "fields": {
 
    "title": "Overview",
 
    "hint": "",
 
    "url": "/programme/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 3,
 
    "sort_order": 12,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 13,
 
  "fields": {
 
    "title": "Miniconfs",
 
    "hint": "",
 
    "url": "/programme/miniconfs/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 3,
 
    "sort_order": 13,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 14,
 
  "fields": {
 
    "title": "Sessions",
 
    "hint": "",
 
    "url": "/programme/sessions/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 3,
 
    "sort_order": 14,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 15,
 
  "fields": {
 
    "title": "Proposals",
 
    "hint": "",
 
    "url": "/programme/proposals/",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": false,
 
    "access_perm_type": 1,
 
    "parent": 3,
 
    "sort_order": 15,
 
    "access_permissions": []
 
  }
 
},
 
{
 
  "model": "sitetree.treeitem",
 
  "pk": 16,
 
  "fields": {
 
    "title": "Admin",
 
    "hint": "",
 
    "url": "#",
 
    "urlaspattern": false,
 
    "tree": 1,
 
    "hidden": false,
 
    "alias": null,
 
    "description": "",
 
    "inmenu": true,
 
    "inbreadcrumbs": true,
 
    "insitetree": true,
 
    "access_loggedin": false,
 
    "access_guest": false,
 
    "access_restricted": true,
 
    "access_perm_type": 1,
 
    "parent": null,
 
    "sort_order": 16,
k8s/deployment_template.jsonnet
Show inline comments
 
function (slug, sha) {
 

	
 
  local app = "symposion-app-" + slug,
 
  local namespace = "rego-review",
 
  local domain = slug + ".dev.lca2019.org",
 
  local tls_secret = slug + "-tls",
 

	
 
  "deployment.json":
 
    {
 
      "apiVersion": "v1",
 
      "items": [
 
        {
 
          "apiVersion": "v1",
 
          "kind": "Service",
 
          "metadata": {
 
            "labels": {
 
              "app":  app,
 
              "slug": slug
 
            },
 
            "name": app,
 
            "namespace": namespace
 
          },
 
          "spec": {
 
            "ports": [
 
              {
 
                "port": 8000,
 
                "protocol": "TCP",
 
                "targetPort": 8000
 
              }
 
            ],
 
            "selector": {
 
              "app": app,
 
              "slug": slug
 
            },
 
            "sessionAffinity": "None",
 
            "type": "ClusterIP"
 
          }
 
        },
 
        {
 
          "apiVersion": "extensions/v1beta1",
 
          "kind": "Deployment",
 
          "metadata": {
 
            "labels": {
 
              "app": app,
 
              "slug": slug,
 
            },
 
            "name": app,
 
            "namespace": namespace
 
          },
 
          "spec": {
 
            "replicas": 1,
 
            "revisionHistoryLimit": 1,
 
            "selector": {
 
              "matchLabels": {
 
                "app": app,
 
                "slug": slug
 
              }
 
            },
 
            "strategy": {
 
              "rollingUpdate": {
 
                "maxSurge": 1,
 
                "maxUnavailable": 1
 
              },
 
              "type": "RollingUpdate"
 
            },
 
            "template": {
 
              "metadata": {
 
                "labels": {
 
                  "app": app,
 
                  "slug": slug
 
                }
 
              },
 
              "spec": {
 
                "containers": [
 
                  {
 
                    "env": [
 
                      {
 
                        "name": "SYMPOSION_APP_DEBUG",
 
                        "value": "1"
 
                      },
 
                      {
 
                        "name": "DJANGO_SECRET_KEY",
 
                        "value": "paGhahQuain5ohYoh0moorai"
 
                      },
 
                      {
 
                        "name": "DATABASE_URL",
 
                        "value": "sqlite:////tmp/symposion.sqlite"
 
                      },
 
                      {
 
                        "name": "GCS_BUCKET",
 
                        "value": "CEA51A5-A613-4AEF-A9FB-D0A57D77C13B"
 
                      },
 
                      {
 
                        "name": "GOOGLE_APPLICATION_CREDENTIALS",
 
                        "value": "/dev/null"
 
                      },
 
                      {
 
                        "name": "STRIPE_PUBLIC_KEY",
 
                        "valueFrom": {
 
                          "secretKeyRef": {
 
                            "key": "STRIPE_PUBLIC_KEY",
 
                            "name": "symposion-app-config"
 
                          }
 
                        }
 
                      },
 
                      {
 
                        "name": "STRIPE_SECRET_KEY",
 
                        "valueFrom": {
 
                          "secretKeyRef": {
 
                            "key": "STRIPE_SECRET_KEY",
 
                            "name": "symposion-app-config"
 
                          }
 
                        }
 
                      },
 
                      {
 
                        "name": "SYMPOSION_DEV_MODE",
 
                        "value": "LAPTOP"
 
                      },
 
                      {
 
                        "name": "ANALYTICS_KEY",
 
                        "value": "UA-000000000-1"
 
                      }
 
                    ],
 
                    "image": "asia.gcr.io/linuxconfsydney/symposion_app_2022_dev:" + sha,
 
                    "image": "registry.gitlab.com/laconfdev/symposion_app/2023:" + sha,
 
                    "imagePullPolicy": "Always",
 
                    "livenessProbe": {
 
                      "failureThreshold": 3,
 
                      "httpGet": {
 
                        "path": "/admin/login/",
 
                        "port": 8000,
 
                        "scheme": "HTTP"
 
                      },
 
                      "initialDelaySeconds": 180,
 
                      "periodSeconds": 10,
 
                      "successThreshold": 1,
 
                      "timeoutSeconds": 5
 
                    },
 
                    "name": app,
 
                    "ports": [
 
                      {
 
                        "containerPort": 8000,
 
                        "protocol": "TCP"
 
                      }
 
                    ],
 
                    "resources": {},
 
                    "terminationMessagePath": "/dev/termination-log",
 
                    "terminationMessagePolicy": "File"
 
                  }
 
                ],
 
                "dnsPolicy": "ClusterFirst",
 
                "restartPolicy": "Always",
 
                "schedulerName": "default-scheduler",
 
                "securityContext": {},
 
                "terminationGracePeriodSeconds": 30
 
              }
 
            }
 
          }
 
        }
 
      ],
 
      "kind": "List"
 
    },
 
  "ingress.json":
 
    {
 
        "kind": "Ingress",
 
        "apiVersion": "extensions/v1beta1",
 
        "metadata": {
 
            "name": app,
 
            "namespace": namespace,
 
            "annotations": {
 
                "kubernetes.io/ingress.class": "nginx-review",
 
            }
 
        },
 
        "spec": {
 
            "backend": {
 
                "serviceName": app,
 
                "servicePort": 80
 
            },
 
            "tls": [
 
                {
 
                    "hosts": [
 
                        domain
 
                    ],
 
                    "secretName": tls_secret,
 
                }
 
            ],
 
            "rules": [
 
                {
 
                    "host": domain,
 
                    "http": {
 
                        "paths": [
 
                            {
 
                                "path": "/",
 
                                "backend": {
 
                                    "serviceName": app,
 
                                    "servicePort": 8000
 
                                }
 
                            }
 
                        ]
 
                    }
 
                }
 
            ]
 
        }
 
    },
 
  "certificate.json":
 
    {
 
      "apiVersion": "certmanager.k8s.io/v1alpha1",
 
      "kind": "Certificate",
 
      "metadata": {
 
        "name": slug,
 
        "namespace": "rego-review",
 
      },
 
      "spec": {
 
        "acme": {
 
          "config": [
 
            {
 
              "domains": [
 
                domain
 
                    ],
 
              "http01": {
 
                      "ingressClass": "nginx-review"
 
                    }
 
                }
 
            ]
 
        },
 
        "commonName": "",
 
        "dnsNames": [
 
            domain
 
        ],
 
        "issuerRef": {
 
            "kind": "ClusterIssuer",
 
            "name": "letsencrypt-prod"
 
        },
 
        "secretName": tls_secret
 
      }
 
    }
 
}
make_dev_container.sh
Show inline comments
 
#!/bin/bash -x
 

	
 
IMAGE_NAME=${1:-symposion_app}
 

	
 
if [ -e ./symposion-tools ]; then
 
    pushd ./symposion-tools
 
    ./save_db_from_docker.sh
 
    popd
 
fi
 

	
 
# Check for docker running
 
if ! docker info >/dev/null 2>&1; then
 
    echo "Docker does not seem to be running. Please start it and retry."
 
    exit 1
 
fi
 

	
 
docker image build -f docker/Dockerfile -t ${IMAGE_NAME} --target symposion_dev .
 
docker container stop symposion
 
docker container rm symposion
 
docker container create --env-file docker/laptop-mode-env -p 28000:8000 -v $(pwd):/app/symposion_app --name symposion ${IMAGE_NAME}
 
docker container start symposion
 
## When we started the container and mounted . into /app/symposion_app, it hides the static/build directory
 
## As a kludge, re-run collectstatic to recreate it
 
## Possible alternative here: don't mount all of ., just mount the bits that we'd live to have update live
 
docker exec symposion ./manage.py collectstatic --noinput -v 0
 
docker exec symposion ./manage.py migrate
 
docker exec symposion ./manage.py loaddata ./fixtures/{conference,sites,sitetree,flatpages}.json
 
docker exec symposion ./manage.py create_review_permissions
 
docker exec symposion ./manage.py loaddata ./fixtures/????/*.json
 
docker exec symposion ./manage.py loaddata ./fixtures/sessions/*.json
 
docker exec symposion ./manage.py populate_inventory
 

	
 
if [ -e ./symposion-tools ]; then
 
    pushd ./symposion-tools
 
    ./fixture_to_docker.sh fixtures/dev_dummy_superuser.json
 
    ./fixture_to_docker.sh fixtures/????_*.json
 
    popd
 
else
 
    echo Now creating a Django superuser. Please enter a
 
    docker exec -it symposion ./manage.py createsuperuser --username admin1 --email root@example.com
 
fi
 

	
 
set +x
 
echo "Now you can log into http://localhost:28000/admin"
 
echo "Username: admin1      Password: the one you just typed twice"
 
echo "If you need to test as a non-admin user, create one at"
 
echo "http://localhost:28000/admin/auth/user/add/ - then log out"
 
echo "and log back in at http://localhost:28000"
pinaxcon/proposals/admin.py
Show inline comments
 
from django.contrib import admin
 

	
 
from pinaxcon.proposals import models
 
from symposion.proposals import models as symposion_models
 
from symposion.reviews.models import ProposalResult
 

	
 
class CategoryAdmin(admin.ModelAdmin):
 

	
 
    class AdditionalSpeakerInline(admin.TabularInline):
 
        model = symposion_models.AdditionalSpeaker
 

	
 
    class ProposalResultInline(admin.TabularInline):
 
        model = ProposalResult
 
        readonly_fields = ["score"]
 
        fields = ["status"]
 

	
 
    inlines = [
 
        AdditionalSpeakerInline,
 
        ProposalResultInline,
 
    ]
 

	
 

	
 
models_to_register = [
 
    models.TalkProposal,
 
    models.TutorialProposal,
 
    models.MiniconfProposal,
 
    ### LCA2022 Miniconfs
 
    models.GlamCommunityProposal,
 
    models.KernelProposal,
 
    models.OpenHardwareProposal,
 
    models.SysAdminProposal,
 
]
 

	
 
for model in models_to_register:
 
    admin.site.register(model, CategoryAdmin,
 
                        list_display = [
 
                            "id",
 
                            "title",
 
                            "speaker",
 
                            "speaker_email",
 
                            "kind",
 
                            "target_audience",
 
                            "status",
 
                            "cancelled",
 
                        ],
 
                        list_filter = [
 
                            "result__status",
 
                            "cancelled",
 
                        ],
 
    )
 

	
pinaxcon/proposals/forms.py
Show inline comments
 
import copy
 

	
 
from django import forms
 

	
 
from pinaxcon.proposals.fields import HelpTextField
 
from pinaxcon.proposals import models
 

	
 

	
 
DEFAULT_FIELDS =  [
 
    "title",
 
    "primary_topic",
 
    "target_audience",
 
    "experience_level",
 
    "abstract",
 
    "private_abstract",
 
    "content_warning",
 
    "technical_requirements",
 
    "project",
 
    "project_url",
 
    "video_url",
 
    "require_approval",
 
    "recording_release",
 
    "materials_release",
 
]
 

	
 
MINICONF_SESSION_FORMAT_FIELDS = copy.copy(DEFAULT_FIELDS)
 

	
 
class ProposalForm(forms.ModelForm):
 

	
 
    required_css_class = 'label-required'
 

	
 
    def clean_description(self):
 
        value = self.cleaned_data["description"]
 
        if len(value) > 400:
 
            raise forms.ValidationError(
 
                u"The description must be less than 400 characters"
 
            )
 
        return value
 

	
 

	
 
class TalkProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.TalkProposal
 
        fields = copy.copy(DEFAULT_FIELDS)
 

	
 

	
 
class TutorialProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.TutorialProposal
 
        fields = copy.copy(DEFAULT_FIELDS)
 

	
 

	
 
class MiniconfProposalForm(ProposalForm):
 

	
 
    class Meta:
 
        model = models.MiniconfProposal
 
        fields = [
 
            "title",
 
            "abstract",
 
            "private_abstract",
 
            "technical_requirements",
 
            "recording_release",
 
            "materials_release",
 
        ]
 

	
 
### LCA2022 Miniconfs
 

	
 
class MiniconfSessionProposalForm(ProposalForm):
 
    pass
 

	
 

	
 
class GlamCommunityProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.GlamCommunityProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
 

	
 

	
 
class KernelProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.KernelProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
 

	
 

	
 
HARDWARE_FIELDS = copy.copy(MINICONF_SESSION_FORMAT_FIELDS)
 
HARDWARE_FIELDS.insert(4, "talk_format")
 

	
 
class OpenHardwareProposalForm(MiniconfSessionProposalForm):
 

	
 
    def __init__(self, *a, **k):
 
        super(OpenHardwareProposalForm, self).__init__(*a, **k)
 
        self.fields['talk_format'].required = True
 

	
 
    class Meta:
 
        model = models.OpenHardwareProposal
 
        fields = HARDWARE_FIELDS
 

	
 

	
 
class SysAdminProposalForm(MiniconfSessionProposalForm):
 

	
 
    class Meta:
 
        model = models.SysAdminProposal
 
        fields = MINICONF_SESSION_FORMAT_FIELDS
pinaxcon/proposals/migrations/0004_auto_20210809_2026.py
Show inline comments
 
deleted file
pinaxcon/proposals/migrations/0004_auto_20221208_0102.py
Show inline comments
 
new file 100644
 
# Generated by Django 2.2.28 on 2022-12-07 14:02
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('symposion_schedule', '0008_auto_20190122_0815'),
 
        ('symposion_reviews', '0001_initial'),
 
        ('symposion_proposals', '0003_auto_20170702_2250'),
 
        ('proposals', '0003_auto_20170702_2227'),
 
    ]
 

	
 
    operations = [
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='content_warning',
 
            field=models.TextField(blank=True, help_text='This will be shown on the schedule to give attendees advanced warning of topics covered in the session. ', verbose_name='Content Warning'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='content_warning_html',
 
            field=models.TextField(blank=True),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='experience_level',
 
            field=models.IntegerField(choices=[(1, 'Beginner'), (2, 'Intermediate'), (3, 'Advanced')], help_text='What level of experience will your session be pitched at?'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='primary_topic',
 
            field=models.IntegerField(choices=[(1, 'Linux'), (2, 'Software'), (3, 'Hardware'), (4, 'Firmware'), (5, 'System Administration / Operations'), (6, 'Security'), (7, 'Documentation'), (8, 'Community'), (9, 'Science & Data'), (10, 'Galleries, Libraries, Archives & Museums (GLAM)'), (11, 'Multimedia'), (12, 'Aerospace / UAV'), (13, 'Agriculture'), (14, 'Other')], help_text='What is the primary topic area for your session?'),
 
        ),
 
        migrations.AddField(
 
            model_name='talkproposal',
 
            name='require_approval',
 
            field=models.BooleanField(default=False, help_text='Do you require further approval from your employer or institution before you can confirm your availability to present?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='content_warning',
 
            field=models.TextField(blank=True, help_text='This will be shown on the schedule to give attendees advanced warning of topics covered in the session. ', verbose_name='Content Warning'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='content_warning_html',
 
            field=models.TextField(blank=True),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='experience_level',
 
            field=models.IntegerField(choices=[(1, 'Beginner'), (2, 'Intermediate'), (3, 'Advanced')], help_text='What level of experience will your session be pitched at?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='primary_topic',
 
            field=models.IntegerField(choices=[(1, 'Linux'), (2, 'Software'), (3, 'Hardware'), (4, 'Firmware'), (5, 'System Administration / Operations'), (6, 'Security'), (7, 'Documentation'), (8, 'Community'), (9, 'Science & Data'), (10, 'Galleries, Libraries, Archives & Museums (GLAM)'), (11, 'Multimedia'), (12, 'Aerospace / UAV'), (13, 'Agriculture'), (14, 'Other')], help_text='What is the primary topic area for your session?'),
 
        ),
 
        migrations.AddField(
 
            model_name='tutorialproposal',
 
            name='require_approval',
 
            field=models.BooleanField(default=False, help_text='Do you require further approval from your employer or institution before you can confirm your availability to present?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='talkproposal',
 
            name='recording_release',
 
            field=models.BooleanField(default=True, help_text="I allow Linux Australia to release any recordings of presentations covered by this proposal, on YouTube under the standard YouTube licence, and on other platforms under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> CC BY-NC-SA 4.0</a>) licence."),
 
        ),
 
        migrations.AlterField(
 
            model_name='talkproposal',
 
            name='target_audience',
 
            field=models.IntegerField(choices=[(4, 'Developer'), (3, 'Community'), (1, 'End User'), (2, 'Business')], help_text='Who is the target audience for your session?'),
 
        ),
 
        migrations.AlterField(
 
            model_name='tutorialproposal',
 
            name='recording_release',
 
            field=models.BooleanField(default=True, help_text="I allow Linux Australia to release any recordings of presentations covered by this proposal, on YouTube under the standard YouTube licence, and on other platforms under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> CC BY-NC-SA 4.0</a>) licence."),
 
        ),
 
        migrations.AlterField(
 
            model_name='tutorialproposal',
 
            name='target_audience',
 
            field=models.IntegerField(choices=[(4, 'Developer'), (3, 'Community'), (1, 'End User'), (2, 'Business')], help_text='Who is the target audience for your session?'),
 
        ),
 
        migrations.DeleteModel(
 
            name='MiniconfProposal',
 
        ),
 
    ]
pinaxcon/proposals/models.py
Show inline comments
 
from django.db import models
 
from django.utils.translation import ugettext_lazy as _
 

	
 
from symposion.proposals.models import ProposalBase
 
from symposion.text_parser import parse
 

	
 

	
 
class Proposal(ProposalBase):
 

	
 
    TARGET_USER = 1
 
    TARGET_BUSINESS = 2
 
    TARGET_COMMUNITY = 3
 
    TARGET_DEVELOPER = 4
 

	
 
    TARGET_AUDIENCES = [
 
        (TARGET_DEVELOPER, "Developer"),
 
        (TARGET_COMMUNITY, "Community"),
 
        (TARGET_USER, "End User"),
 
        (TARGET_BUSINESS, "Business"),
 
    ]
 

	
 
    TOPIC_LINUX = 1
 
    TOPIC_SOFTWARE = 2
 
    TOPIC_HARDWARE = 3
 
    TOPIC_FIRMWARE = 4
 
    TOPIC_SYSADMIN = 5
 
    TOPIC_SECURITY = 6
 
    TOPIC_DOCUMENTATION = 7
 
    TOPIC_COMMUNITY = 8
 
    TOPIC_SCIENCE = 9
 
    TOPIC_GLAM = 10
 
    TOPIC_MULTIMEDIA = 11
 
    TOPIC_AEROSPACE = 12
 
    TOPIC_AGRICULTURE = 13
 
    TOPIC_OTHER = 14
 

	
 
    PROPOSAL_TOPIC = [
 
        (TOPIC_LINUX, "Linux"),
 
        (TOPIC_SOFTWARE, "Software"),
 
        (TOPIC_HARDWARE, "Hardware"),
 
        (TOPIC_FIRMWARE, "Firmware"),
 
        (TOPIC_SYSADMIN, "System Administration / Operations"),
 
        (TOPIC_SECURITY, "Security"),
 
        (TOPIC_DOCUMENTATION, "Documentation"),
 
        (TOPIC_COMMUNITY, "Community"),
 
        (TOPIC_SCIENCE, "Science & Data"),
 
        (TOPIC_GLAM, "Galleries, Libraries, Archives & Museums (GLAM)"),
 
        (TOPIC_MULTIMEDIA, "Multimedia"),
 
        (TOPIC_AEROSPACE, "Aerospace / UAV"),
 
        (TOPIC_AGRICULTURE, "Agriculture"),
 
        (TOPIC_OTHER, "Other"),
 
    ]
 

	
 
    LEVEL_BEGINNER = 1
 
    LEVEL_INTERMEDIATE = 2
 
    LEVEL_ADVANCED = 3
 

	
 
    EXPERIENCE_LEVEL = [
 
        (LEVEL_BEGINNER, "Beginner"),
 
        (LEVEL_INTERMEDIATE, "Intermediate"),
 
        (LEVEL_ADVANCED, "Advanced"),
 
    ]
 

	
 
    target_audience = models.IntegerField(
 
        choices=TARGET_AUDIENCES,
 
        help_text="Who is the target audience for your session?",
 
    )
 

	
 
    recording_release = models.BooleanField(
 
        default=True,
 
        help_text="I allow Linux Australia to release any recordings of "
 
        "presentations covered by this proposal, on YouTube under the "
 
        "standard YouTube licence, and on other platforms under the "
 
        "Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International "
 
        "(<a href='https://creativecommons.org/licenses/by-nc-sa/4.0/'> "
 
        "CC BY-NC-SA 4.0</a>) licence."
 
    )
 

	
 
    materials_release = models.BooleanField(
 
        default=True,
 
        help_text="I allow Linux Australia to release any other material "
 
        "(such as slides) from presentations covered by this proposal, under "
 
        "the <a "
 
        "href='https://creativecommons.org/licenses/by-sa/3.0/au/deed.en'> "
 
        "Creative Commons Attribution-Share Alike Australia 3.0 Licence</a>"
 
    )
 

	
 
    class Meta:
 
        abstract = True
 

	
 

	
 
class SessionProposal(Proposal):
 
    """
 
    Base Session Proposal
 

	
 
    This is not a meta class as we want a single table to store the common
 
    data across all session proposal types.
 
    """
 

	
 
    TOPIC_SOFTWARE = 1
 
    TOPIC_HARDWARE = 2
 
    TOPIC_FIRMWARE = 3
 
    TOPIC_KERNEL = 4
 
    TOPIC_DOCUMENTATION = 5
 
    TOPIC_COMMUNITY = 6
 
    TOPIC_SECURITY = 7
 
    TOPIC_OPERATIONS = 8
 
    TOPIC_OTHER = 9
 

	
 
    PROPOSAL_TOPIC = [
 
        (TOPIC_SOFTWARE, "Software"),
 
        (TOPIC_HARDWARE, "Hardware"),
 
        (TOPIC_FIRMWARE, "Firmware"),
 
        (TOPIC_KERNEL, "Linux Kernel"),
 
        (TOPIC_DOCUMENTATION, "Documentation"),
 
        (TOPIC_COMMUNITY, "Community"),
 
        (TOPIC_SECURITY, "Security"),
 
        (TOPIC_OPERATIONS, "Deployment & Operations"),
 
        (TOPIC_OTHER, "Other"),
 
    ]
 

	
 
    LEVEL_BEGINNER = 1
 
    LEVEL_INTERMEDIATE = 2
 
    LEVEL_ADVANCED = 3
 

	
 
    EXPERIENCE_LEVEL = [
 
        (LEVEL_BEGINNER, "Beginner"),
 
        (LEVEL_INTERMEDIATE, "Intermediate"),
 
        (LEVEL_ADVANCED, "Advanced"),
 
    ]
 

	
 
    primary_topic = models.IntegerField(
 
        choices=PROPOSAL_TOPIC,
 
        help_text="What is the primary topic area for your session?"
 
    )
 

	
 
    experience_level = models.IntegerField(
 
        choices=EXPERIENCE_LEVEL,
 
        help_text="What level of experience will your session be pitched at?"
 
    )
 

	
 
    require_approval = models.BooleanField(
 
        default=False,
 
        help_text="Do you require further approval from your employer or "
 
        "institution before you can confirm your availability to present?"
 
    )
 

	
 

	
 
class TalkProposal(SessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "talk proposal"
 

	
 

	
 
class TutorialProposal(SessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "tutorial proposal"
 

	
 

	
 
class MiniconfProposal(Proposal):
 
    """
 
    Miniconf Proposal
 

	
 
    Note that this is just a Proposal, not a SessionProposal, as it does not
 
    require a number of fields that the others use.
 
    """
 

	
 
    target_audience = models.IntegerField(choices=Proposal.TARGET_AUDIENCES,
 
                                          default=Proposal.TARGET_DEVELOPER)
 

	
 
    class Meta:
 
        verbose_name = "miniconf proposal"
 

	
 

	
 
class MiniconfSessionProposal(SessionProposal):
 
    """
 
    Base Miniconf Session Proposal
 
    """
 
    content_warning = models.TextField(
 
        "Content Warning",
 
        help_text=_("This will be shown on the schedule to give attendees "
 
                    "advanced warning of topics covered in the session. "),
 
        blank=True,
 
    )
 
    content_warning_html = models.TextField(blank=True)
 

	
 
    class Meta:
 
        abstract = True
 

	
 
    def save(self, *args, **kwargs):
 
        self.content_warning_html = parse(self.content_warning)
 
        return super(Proposal, self).save(*args, **kwargs)
 

	
 
class GlamCommunityProposal(MiniconfSessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "GO GLAM Miniconf Proposal"
 

	
 

	
 
class KernelProposal(MiniconfSessionProposal):
 

	
 
    class Meta:
 
        verbose_name = "Kernel Miniconf Proposal"
 

	
 

	
 
class OpenHardwareProposal(MiniconfSessionProposal):
 

	
 
    FORMAT_PRESENTATION = 1
 
    FORMAT_TUTORIAL = 2
 
    FORMAT_HANDS_ON = 3
 

	
 
    TALK_FORMATS = [
 
        (FORMAT_PRESENTATION, "Presentation"),
 
        (FORMAT_TUTORIAL, "Tutorial"),
 
        (FORMAT_HANDS_ON, "Hands-on"),
 
    ]
 

	
 
    talk_format = models.IntegerField(
 
        choices=TALK_FORMATS,
 
        default=FORMAT_PRESENTATION,
 
        help_text="Will your session be a presentation, tutorial or hands-on "
 
        "(e.g how to use KiCAD or some other tooling)?"
 
    )
 
class TalkProposal(Proposal):
 

	
 
    class Meta:
 
        verbose_name = "Open Hardware Miniconf Proposal"
 
        verbose_name = "talk proposal"
 

	
 

	
 
class SysAdminProposal(MiniconfSessionProposal):
 
class TutorialProposal(Proposal):
 

	
 
    class Meta:
 
        verbose_name = "System Administration Miniconf Proposal"
 
        verbose_name = "tutorial proposal"
pinaxcon/registrasion/forms.py
Show inline comments
 
from pinaxcon.registrasion import models
 

	
 
from django import forms
 

	
 

	
 
class YesNoField(forms.TypedChoiceField):
 

	
 
    def __init__(self, *args, **kwargs):
 
        kwargs['required'] = True
 
        super(YesNoField, self).__init__(
 
            *args,
 
            coerce=lambda x: x in ['True', 'Yes', True],
 
            choices=((None, '--------'), (False, 'No'), (True, 'Yes')),
 
            **kwargs
 
        )
 

	
 

	
 
class ProfileForm(forms.ModelForm):
 
    ''' A form for requesting badge and profile information. '''
 

	
 
    required_css_class = 'label-required'
 

	
 
    class Meta:
 
        model = models.AttendeeProfile
 
        exclude = [
 
            'attendee',
 
            'children',
 
            'lca_announce',
 
            'lca_chat',
 
            'future_conference',
 
        ]
 
        widgets = {
 
            'past_lca': forms.widgets.CheckboxSelectMultiple
 
        }
 
        field_classes = {
 
            "of_legal_age": YesNoField,
 
        }
pinaxcon/registrasion/management/commands/populate_inventory.py
Show inline comments
 
from collections import namedtuple
 
from datetime import timedelta
 
from decimal import Decimal
 
from django.conf import settings
 
from django.contrib.auth.models import Group
 
from django.core.exceptions import ObjectDoesNotExist
 
from django.core.management.base import BaseCommand
 

	
 
from registrasion.models import inventory as inv
 
from registrasion.models import conditions as cond
 
from symposion import proposals
 

	
 

	
 
class Command(BaseCommand):
 
    help = 'Populates the tickets and product inventory models'
 
    count = 0
 

	
 
    def add_arguments(self, parser):
 
        pass
 

	
 
    def handle(self, *args, **options):
 

	
 
        kinds = []
 
        for i in settings.MAIN_CONFERENCE_PROPOSAL_KINDS:
 
            kinds.append(proposals.models.ProposalKind.objects.get(name=i))
 
        self.main_conference_proposals = kinds
 

	
 
        self.populate_groups()
 
        self.populate_inventory()
 
        self.populate_restrictions()
 
        self.populate_discounts()
 

	
 
    def populate_groups(self):
 
        self.group_team = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Conference organisers",
 
        )
 
        self.group_volunteers = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Conference volunteers",
 
        )
 
        self.group_unpublish = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Can see unpublished products",
 
        )
 
        self.group_prepurchase = self.find_or_make(
 
            Group,
 
            ("name", ),
 
            name="Pre-purchase",
 
        )
 

	
 
    def populate_inventory(self):
 
        # Categories
 

	
 
        self.ticket = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Ticket",
 
            description="Each type of ticket has different included products. "
 
                        "For details of what products are included, see our "
 
                        "<a href=\"/attend/tickets/\">registration page</a>.",
 
            required=True,
 
            render_type=inv.Category.RENDER_TYPE_RADIO,
 
            limit_per_user=1,
 
            order=1,
 
        )
 
        self.terms = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Terms, Conditions, and Code of Conduct Acceptance",
 
            description="I agree to the "
 
                        "<a href=\"/attend/terms-and-conditions/\"> "
 
                        "terms and conditions of attendance</a>, and I have read, "
 
                        "understood, and agree to act according to the standards set "
 
                        "forth in our <a href=\"/attend/code-of-conduct/\">"
 
                        "Code of Conduct</a>.",
 
            required=True,
 
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
 
            order=10,
 
        )
 
        # self.penguin_dinner = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Penguin Dinner Ticket",
 
        #     description="Tickets to our conference dinner on the evening of "
 
        #                 f"{settings.PENGUIN_DINNER_TICKET_DATE: %A %d %B}. "
 
        #                 "All attendees may purchase "
 
        #                 "seats at the dinner, even if a dinner ticket is not "
 
        #                 "included in your conference ticket price.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
        #     limit_per_user=10,
 
        #     order=20,
 
        # )
 
        # self.speakers_dinner_ticket = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Speakers' Dinner Ticket",
 
        #     description="Tickets to our exclusive Speakers' Dinner on the "
 
        #                 "evening of "
 
        #                 f"{settings.SPEAKER_DINNER_TICKET_DATE: %A %d %B}.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
        #     limit_per_user=1,
 
        #     order=30,
 
        # )
 
        # self.pdns_category = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Professional Delegates Networking Session Ticket",
 
        #     description="Tickets to our Professional Delegates Networking session. "
 
        #                 "This event will be held on the evening of "
 
        #                 f"{settings.PDNS_TICKET_DATE: %A %d %B} "
 
        #                 "and is restricted to Professional Ticket "
 
        #                 "holders, speakers, miniconf organisers, and invited "
 
        #                 "guests.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=40,
 
        # )
 
        # self.t_shirt = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Shirt",
 
        #     description="Commemorative conference shirts, featuring the "
 
        #                 f"linux.conf.au {settings.LCA_START.year} artwork. "
 
        #                 f"linux.conf.au {settings.CONF_START.year} artwork. "
 
        #                 "View the <a href=\"/attend/shirts/\">"
 
        #                 "sizing guide</a>.",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
 
        #     order=50,
 
        # )
 
        # self.accommodation = self.find_or_make(
 
        #     inv.Category,
 
        #     ("name",),
 
        #     name="Accommodation at University of Tasmania",
 
        #     description="Accommodation at the University of Tasmania colleges "
 
        #                 "and apartments. You can come back and book your "
 
        #                 "accommodation at a later date, provided rooms remain "
 
        #                 "available. Rooms may only be booked from Sunday 15 "
 
        #                 "January--Saturday 21 January. If you wish to stay "
 
        #                 "for only a part of the 6-day period, you must book "
 
        #                 "accommodation for the full 6-day period. Rooms at "
 
        #                 "other hotels, including Wrest Point can be booked "
 
        #                 "elsewhere. For full details, see [LINK]our "
 
        #                 "accommodation page.[/LINK]",
 
        #     required=False,
 
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
 
        #     limit_per_user=1,
 
        #     order=50,
 
        # )
 
        self.badge_category = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Swag Badge",
 
            description="We have a limited number of "
 
                        "<a href=\"/attend/shirts/\">Swag Badges</a> available "
 
                        f"for attendees of {settings.CONFERENCE_NAME}. "
 
                        "They will be allocated on a first come, first serve basis. "
 
                        "Please note that they are only available to Australian "
 
                        "attendees due to shipping limitations.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
 
            order=50,
 
        )
 
        self.extras = self.find_or_make(
 
            inv.Category,
 
            ("name",),
 
            name="Extras",
 
            description="Other items that can improve your conference "
 
                        "experience.",
 
            required=False,
 
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
 
            order=60,
 
        )
 

	
 
        # Tickets
 

	
 
        self.ticket_contributor = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.CONTRIBUTOR.name,
 
            price=settings.CONTRIBUTOR.regular_price,
 
            reservation_duration=hours(24),
 
            order=1,
 
        )
 
        self.ticket_professional = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.PROFESSIONAL.name,
 
            price=settings.PROFESSIONAL.regular_price,
 
            reservation_duration=hours(24),
 
            order=10,
 
        )
 
        self.ticket_hobbyist = self.find_or_make(
 
            inv.Product,
 
            ("name", "category",),
 
            category=self.ticket,
 
            name=settings.HOBBYIST.name,
 
</