Compare commits

..

33 Commits

Author SHA1 Message Date
Loïc Dachary eaff09efd4 Merge pull request 'do not rename past migrations' (#73) from dachary/dashboard:wip-forgejo into master
ci/woodpecker/push/woodpecker Pipeline failed Details
Reviewed-on: #73
2023-01-09 12:59:42 -05:00
Loïc Dachary d07a644552
upgrade greenlet 1.1.3.post0
ci/woodpecker/pr/woodpecker Pipeline failed Details
ci/woodpecker/push/woodpecker Pipeline failed Details
2023-01-09 18:51:22 +01:00
Loïc Dachary 93c38fc1f9
Forgejo is codeberg.org/forgejo/forgejo:1.18.0-1
ci/woodpecker/pr/woodpecker Pipeline failed Details
ci/woodpecker/push/woodpecker Pipeline failed Details
2023-01-09 18:39:35 +01:00
Loïc Dachary 788e025b98
do not rename past migrations
ci/woodpecker/pr/woodpecker Pipeline failed Details
it is not possible to go back in time
2023-01-09 18:24:10 +01:00
Loïc Dachary 1c165fcea3
upgrade gitea to forgejo
ci/woodpecker/pr/woodpecker Pipeline failed Details
ci/woodpecker/push/woodpecker Pipeline failed Details
Signed-off-by: Loïc Dachary <loic@dachary.org>
2022-12-23 22:34:38 +01:00
Aravinth Manivannan 2e36a186ee Merge pull request 'convert instance names to lowercase' (#70) from dachary/dashboard:wip-lowercase into master
ci/woodpecker/push/woodpecker Pipeline failed Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/70
2022-10-04 04:39:04 -04:00
Loïc Dachary ad925cddfc
convert instance names to lowercase
ci/woodpecker/pr/woodpecker Pipeline was successful Details
Fixes: https://gitea.gna.org/Hostea/dashboard/issues/69

Signed-off-by: Loïc Dachary <loic@dachary.org>
2022-10-04 09:14:50 +02:00
Loïc Dachary 2725b9b1f6
avoid crash in CI when STRIPE is not set
Signed-off-by: Loïc Dachary <loic@dachary.org>
2022-10-04 09:14:50 +02:00
Loïc Dachary 0f1003dbe8 Merge pull request 'fix: receipt email subject' (#68) from fix-email-typo into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/68
2022-10-01 12:01:08 -04:00
Aravinth Manivannan 187d22118f Merge pull request 'do not pin Gitea version' (#67) from dachary/dashboard:wip-gitea into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/67
2022-10-01 07:55:12 -04:00
Hostea dashboard 9b9fb8362d
fix: receipt email subject
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
2022-09-30 18:36:56 +05:30
Loïc Dachary 498b95848e
do not pin Gitea version
ci/woodpecker/pr/woodpecker Pipeline failed Details
So that it is upgraded when Enough is upgraded.

Signed-off-by: Loïc Dachary <loic@dachary.org>
2022-09-30 14:54:50 +02:00
Loïc Dachary b5afc49f5d Merge pull request 'notify staff when new instance is deployed' (#61) from alert-staff-new-instance into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/61
2022-09-14 02:48:21 -04:00
Hostea dashboard 86fe9a2c59
feat: alert staff on new instance creation
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
closes: https://gitea.gna.org/Hostea/dashboard/issues/52
2022-09-13 19:57:37 +05:30
Hostea dashboard 9d2a53f2e2
fix: more email project renaming 2022-09-13 19:57:26 +05:30
Loïc Dachary c7def47215 Merge pull request 'fix: don't send pre-payment notification email' (#56) from fix-rm-not-invoice into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/56
2022-09-12 15:48:14 -04:00
Hostea dashboard 9f5032bd28
feat: send subscription renewal notification emails
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
2022-09-12 21:01:24 +05:30
Hostea dashboard 669a22a004
fix: don't send pre-payment notification email
closes: https://gitea.gna.org/Hostea/dashboard/issues/49
2022-09-12 21:01:21 +05:30
Loïc Dachary 0ab82fe0b4 Merge pull request 'fix: rename Gna! in emails' (#60) from fix-rename-gna-in-emails into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/60
2022-09-12 08:36:17 -04:00
Hostea dashboard 0e0b8db940
fix: test for Gna! in emails
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
2022-09-12 17:36:24 +05:30
Hostea dashboard ac0775e075
fix: rename to Gna! in email templates 2022-09-12 17:36:04 +05:30
Hostea dashboard 51e7ea4d5e
fix: rename Gna! in emails
ci/woodpecker/push/woodpecker Pipeline failed Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
2022-09-12 16:36:29 +05:30
Loïc Dachary 98973301c3 Merge pull request 'fix: don't send emails to VMs that were requested but not created' (#54) from fix-dead-instance-invoices into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/54
2022-09-11 19:07:41 -04:00
Hostea dashboard 3ebc518e1f
fix: don't send emails to VMs that were requested but not created
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
SUMMARY
    dash.models.Instance is created upon request and
    infrastructure.models.InstanceCreated when the instance is created.
    Using data from InstanceCreated to send invoices should solve this
    issue.
2022-09-12 04:05:41 +05:30
Aravinth Manivannan 25db390e4d Merge pull request 'Rename hostea to gna!' (#59) from wip-rename-hostea-to-gna into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/59
2022-09-11 18:25:58 -04:00
Hostea dashboard 6365b84d45
feat: run collectstatic before launching development server to update static assets
ci/woodpecker/push/woodpecker Pipeline was successful Details
ci/woodpecker/pr/woodpecker Pipeline failed Details
2022-09-12 03:53:19 +05:30
Hostea dashboard 41ca63244e
feat: update name and web links to Gna! 2022-09-12 03:53:19 +05:30
Hostea dashboard 0e2112e30f
feat: change hostea logo to gna! 2022-09-12 03:53:19 +05:30
Loïc Dachary 5b7cf06c7a Merge pull request 'fix: instance_names in tests must be alphanumeric and be < 20 chars' (#58) from fix-hostname-validation into master
ci/woodpecker/push/woodpecker Pipeline was successful Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/58
2022-09-11 18:13:12 -04:00
Hostea dashboard 1792713952
fix: instance_names in tests must be alphanumeric and be < 20 chars
ci/woodpecker/pr/woodpecker Pipeline failed Details
ci/woodpecker/push/woodpecker Pipeline was successful Details
closes: https://gitea.gna.org/Hostea/dashboard/issues/57
2022-09-12 03:33:20 +05:30
Loïc Dachary 3019d9d739 Merge pull request 'fix: add hostname validation rules' (#55) from fix-hostname-validation into master
ci/woodpecker/push/woodpecker Pipeline failed Details
Reviewed-on: https://gitea.gna.org/Hostea/dashboard/pulls/55
2022-09-11 16:11:58 -04:00
Hostea dashboard bcb2e26f61
feat: test vm name validation 2022-09-04 18:04:37 +05:30
Hostea dashboard 011fb4816f
fix: validate VM names
fixes: https://gitea.gna.org/Hostea/dashboard/issues/51
2022-09-04 17:49:53 +05:30
90 changed files with 568 additions and 419 deletions

View File

@ -3,5 +3,5 @@ export db=""
export STRIPE_SECRET_KEY="" export STRIPE_SECRET_KEY=""
export STRIPE_PUBLIC_KEY="" export STRIPE_PUBLIC_KEY=""
export HOSTEA_INFRA_HOSTEA_REPO_REMOTE="ssh://git@localhost:22/hostea/fleet.git" export HOSTEA_INFRA_HOSTEA_REPO_REMOTE="ssh://git@localhost:22/hostea/fleet.git"
export HOSTEA_META_GITEA_INSTANCE="http://localhost:3000" export HOSTEA_META_FORGEJO_INSTANCE="http://localhost:3000"
export HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY="$(realpath ./tests/fleet-deploy-key)" export HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY="$(realpath ./tests/fleet-deploy-key)"

View File

@ -4,8 +4,8 @@ pipeline:
environment: environment:
- DATABSE_URL=postgres://postgres:password@database:5432/postgres - DATABSE_URL=postgres://postgres:password@database:5432/postgres
- EMAIL_URL=smtp://admin:password@smtp:10025 - EMAIL_URL=smtp://admin:password@smtp:10025
- HOSTEA_INFRA_HOSTEA_REPO_REMOTE=ssh://git@gitea:22/hostea/ - HOSTEA_INFRA_HOSTEA_REPO_REMOTE=ssh://git@forgejo:22/hostea/
- HOSTEA_META_GITEA_INSTANCE=http://gitea:3000 - HOSTEA_META_FORGEJO_INSTANCE=http://forgejo:3000
commands: commands:
- export HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY="$(realpath ./tests/fleet-deploy-key)" - export HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY="$(realpath ./tests/fleet-deploy-key)"
- pip install virtualenv - pip install virtualenv
@ -21,9 +21,9 @@ services:
environment: environment:
- POSTGRES_PASSWORD=password - POSTGRES_PASSWORD=password
gitea: forgejo:
image: gitea/gitea:1.16.5 image: codeberg.org/forgejo/forgejo:1.18.0-1
container_name: hostea-dash-gitea container_name: hostea-dash-forgejo
smtp: smtp:
image: maildev/maildev:latest image: maildev/maildev:latest

View File

@ -1,6 +1,6 @@
FROM python FROM python
LABEL org.opencontainers.image.source https://gitea.hostea.org/Hostea/dashboard LABEL org.opencontainers.image.source https://forgejo.hostea.org/Hostea/dashboard
RUN useradd -ms /bin/bash -u 1001 hostea RUN useradd -ms /bin/bash -u 1001 hostea
RUN apt-get update && apt-get install -y ca-certificates git RUN apt-get update && apt-get install -y ca-certificates git

View File

@ -9,6 +9,7 @@ endef
default: ## Run app default: ## Run app
$(call run_migrations) $(call run_migrations)
. ./venv/bin/activate && yes yes | python manage.py collectstatic
. ./venv/bin/activate && python manage.py runserver . ./venv/bin/activate && python manage.py runserver
coverage: ## Generate test coverage report coverage: ## Generate test coverage report

View File

@ -2,7 +2,7 @@
# Hostea dashboard # Hostea dashboard
[![status-badge](https://woodpecker.hostea.org/api/badges/Hostea/dashboard/status.svg)](https://woodpecker.hostea.org/Hostea/dashboard) [![status-badge](https://woodpecker.gna.org/api/badges/Hostea/dashboard/status.svg)](https://woodpecker.gna.org/Hostea/dashboard)
[![AGPL License](https://img.shields.io/badge/license-AGPL-blue.svg?style=flat-square)](http://www.gnu.org/licenses/agpl-3.0) [![AGPL License](https://img.shields.io/badge/license-AGPL-blue.svg?style=flat-square)](http://www.gnu.org/licenses/agpl-3.0)
[![Chat](https://img.shields.io/badge/matrix-hostea:matrix.batsense.net-purple?style=flat-square)](https://matrix.to/#/#hostea:matrix.batsense.net) [![Chat](https://img.shields.io/badge/matrix-hostea:matrix.batsense.net-purple?style=flat-square)](https://matrix.to/#/#hostea:matrix.batsense.net)

View File

@ -1,22 +1,22 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %}{% block title_name %} {% endblock %} | Hostea Dashbaord{% endblock %} {% block title %}{% block title_name %} {% endblock %} | Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<main class="auth__main"> <main class="auth__main">
<section class="main"> <section class="main">
<div class="title"> <div class="title">
<h1><a href="https://gitea.io">Gitea</a> hosting and <a href="/gitea-clinic/">service</a></h1> <h1><a href="https://forgejo.org">Forgejo</a> hosting and <a href="/forgejo-clinic/">service</a></h1>
<p class="welcome"> <p class="welcome">
A free forge ecosystem for free developers. A free forge ecosystem for free developers.
</p> </p>
<ul class="index-banner__features-list"> <ul class="index-banner__features-list">
<li class="index-banner__features">Dedicated <a href="https://hosteadashboard.hostea.org/register/">Gitea hosting</a> and <a href="https://woodpecker-ci.org/">Woodpecker CI</a> from 10€/month</li> <li class="index-banner__features">Dedicated <a href="https://hosteadashboard.gna.org/register/">Forgejo hosting</a> and <a href="https://woodpecker-ci.org/">Woodpecker CI</a> from 10€/month</li>
<li class="index-banner__features">Clinic to <a href="https://hostea.org/gitea-clinic/">heal sick Gitea</a> instances</li> <li class="index-banner__features">Clinic to <a href="https://gna.org/forgejo-clinic/">heal sick Forgejo</a> instances</li>
<li class="index-banner__features">100% <a href="https://www.gnu.org/philosophy/free-sw.html">Free Software</a></li> <li class="index-banner__features">100% <a href="https://www.gnu.org/philosophy/free-sw.html">Free Software</a></li>
<li class="index-banner__features">Radically <a href="https://forum.hostea.org/t/about-governance-and-decisions-in-hostea/55">Transparent</a></li> <li class="index-banner__features">Radically <a href="https://forum.gna.org/t/about-governance-and-decisions-in-hostea/55">Transparent</a></li>
<li class="index-banner__features">Run by a <a href="https://forum.hostea.org/t/about-governance-and-decisions-in-hostea/55">horizontal collective</a></li> <li class="index-banner__features">Run by a <a href="https://forum.gna.org/t/about-governance-and-decisions-in-hostea/55">horizontal collective</a></li>
<li class="index-banner__features">25% of the income <a href="https://forum.hostea.org/t/decision-revenue-sharing-model/92">dedicated to sustain Free Software dependencies</a></li> <li class="index-banner__features">25% of the income <a href="https://forum.gna.org/t/decision-revenue-sharing-model/92">dedicated to sustain Free Software dependencies</a></li>
<li class="index-banner__features">Committed to <a href="https://forgefriends.org/blog/2022/06/30/2022-06-state-forge-federation/">further forge federation</a></li> <li class="index-banner__features">Committed to <a href="https://forgefriends.org/blog/2022/06/30/2022-06-state-forge-federation/">further forge federation</a></li>
</ul> </ul>
</div> </div>

View File

@ -39,7 +39,7 @@
</div> </div>
</form> </form>
<p class="form__alt-action"> <p class="form__alt-action">
New to Hostea? New to Gna!?
<a href="{% url 'accounts.register' %}">Create an account</a> <a href="{% url 'accounts.register' %}">Create an account</a>
</p> </p>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Reset Password| Hostea Dashboard{% endblock %} {% block title %} Reset Password| Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<div class="dialogue-box__container"> <div class="dialogue-box__container">

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Reset Password | Hostea Dashboard{% endblock %} {% block title %} Reset Password | Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<div class="dialogue-box__container"> <div class="dialogue-box__container">

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Reset Password | Hostea Dashboard{% endblock %} {% block title %} Reset Password | Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<div class="dialogue-box__container"> <div class="dialogue-box__container">

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Confirm Access | Hostea Dashbaord{% endblock %} {% block title %} Confirm Access | Gna! Dashboard{% endblock %}
{% block nav %} {% include "dash/common/components/primary-nav.html" %} {% endblock %} {% block nav %} {% include "dash/common/components/primary-nav.html" %} {% endblock %}
{% block main %} {% block main %}

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Confirm Account | Hostea Dashbaord{% endblock %} {% block title %} Confirm Account | Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<div class="dialogue-box__container"> <div class="dialogue-box__container">

View File

@ -1,5 +1,5 @@
{% extends "common/components/base.html" %} {% extends "common/components/base.html" %}
{% block title %} Confirm Account | Hostea Dashbaord{% endblock %} {% block title %} Confirm Account | Gna! Dashboard{% endblock %}
{% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %} {% block nav %} {% include "common/components/nav/pub.html" %} {% endblock %}
{% block main %} {% block main %}
<div class="dialogue-box__container"> <div class="dialogue-box__container">

View File

@ -2,7 +2,7 @@ Hello {{ username }},
You have a new password! You have a new password!
Your password for signing in to Hostea was recently changed. If you made this change, then we're all set. Your password for signing in to Gna! was recently changed. If you made this change, then we're all set.
If you did not make this change, please reset your password to secure your account. If you did not make this change, please reset your password to secure your account.
@ -11,4 +11,4 @@ If you did not make this change, please reset your password to secure your accou
Either way, feel free to reach out with any questions you might have. We're here to help. Either way, feel free to reach out with any questions you might have. We're here to help.
Cheers, Cheers,
Hostea team Gna! team

View File

@ -6,4 +6,4 @@ Please click on the link below to reset your password:
If you don't recognise this activity, please delete this mail. If you don't recognise this activity, please delete this mail.
Cheers, Cheers,
Hostea team Gna! team

View File

@ -6,4 +6,4 @@ Please click on the link below to verify your email.
If you don't recognise this activity, please delete this mail. If you don't recognise this activity, please delete this mail.
Cheers, Cheers,
Hostea team Gna! team

View File

@ -10,21 +10,11 @@
title="RSS" title="RSS"
>Home</a> >Home</a>
<span class="footer__column-divider--mobile-visible">|</span> <span class="footer__column-divider--mobile-visible">|</span>
<a class="license__link" rel="noreferrer" href="https://hostea.org/about" target="_blank" <a class="license__link" rel="noreferrer" href="https://gna.org/about" target="_blank"
>&nbsp; About</a >&nbsp; About</a
> >
</span> </span>
</div> </div>
<div class="footer__column">
<a
class="license__link"
rel="noreferrer"
href="https://www.eff.org/issues/do-not-track/amp/"
target="_blank"
>No AMP</a
>
<div class="footer__column-divider">|</div>
<a href="mailto:{{ footer.admin_email }}" class="footer__link" <a href="mailto:{{ footer.admin_email }}" class="footer__link"
>Contact Instance Maintainer</a >Contact Instance Maintainer</a
> >

View File

@ -3,11 +3,8 @@
<input type="checkbox" class="nav__toggle" id="nav__toggle" /> <input type="checkbox" class="nav__toggle" id="nav__toggle" />
<div class="nav__header"> <div class="nav__header">
<a class="nav__logo-container" href="/"> <a class="nav__logo-container" href="/">
<img src="{% static 'img/android-icon-48x48.png' %}" <img class="nav__logo-img" src="{% static 'img/logo.png' %}"
alt="Hostea temporary logo"/> alt="Gna! logo"/>
<p class="nav__home-btn">
ostea
</p>
</a> </a>
<label class="nav__hamburger-menu" for="nav__toggle"> <label class="nav__hamburger-menu" for="nav__toggle">
<span class="nav__hamburger-inner"></span> <span class="nav__hamburger-inner"></span>

View File

@ -77,7 +77,9 @@ class LoginTest(TestCase):
Tests if login template renders Tests if login template renders
""" """
resp = self.client.get(reverse("accounts.login")) resp = self.client.get(reverse("accounts.login"))
self.assertEqual(b"A free forge ecosystem for free developers" in resp.content, True) self.assertEqual(
b"A free forge ecosystem for free developers" in resp.content, True
)
def test_login_works(self): def test_login_works(self):
""" """
@ -234,7 +236,9 @@ class RegistrationTest(TestCase):
Tests if register template renders Tests if register template renders
""" """
resp = self.client.get(reverse("accounts.register")) resp = self.client.get(reverse("accounts.register"))
self.assertEqual(b"A free forge ecosystem for free developers." in resp.content, True) self.assertEqual(
b"A free forge ecosystem for free developers." in resp.content, True
)
def test_register_works(self): def test_register_works(self):
""" """

View File

@ -45,9 +45,9 @@ def send_password_changed_email(request):
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Password changed", subject="[Gna!] Password changed",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", from_email=f"No reply Gna!<{sender}>",
recipient_list=[email], recipient_list=[email],
) )
@ -72,9 +72,9 @@ def send_password_reset_email(request, challenge):
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Password reset link", subject="[Gna!] Password reset link",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", from_email=f"No reply Gna!<{sender}>",
recipient_list=[email], recipient_list=[email],
) )
@ -99,9 +99,9 @@ def send_verification_email(request, challenge):
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Please confirm your email address", subject="[Gna!] Please confirm your email address",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", from_email=f"No reply Gna!<{sender}>",
recipient_list=[email], recipient_list=[email],
) )

View File

@ -15,6 +15,8 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.conf import settings from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from oauth2_provider.models import get_application_model from oauth2_provider.models import get_application_model
@ -22,7 +24,8 @@ from oauth2_provider.generators import generate_client_id, generate_client_secre
from accounts.utils import gen_secret from accounts.utils import gen_secret
from dash.models import Instance from dash.models import Instance
from billing.utils import generate_invoice, payment_fullfilled from infrastructure.models import InstanceCreated
from billing.utils import generate_invoice, payment_fullfilled, get_invoice_link
Application = get_application_model() Application = get_application_model()
@ -33,10 +36,34 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
instances = Instance.objects.all() instances = Instance.objects.all()
if instances: if instances:
for instance in Instance.objects.all(): for paid_instance in InstanceCreated.objects.all():
self.stdout.write(f"Found instance: {instance}") self.stdout.write(f"Found instance: {paid_instance.instance}")
if not payment_fullfilled(instance=instance): if not payment_fullfilled(instance=paid_instance.instance):
self.stdout.write(f"Payment not fulfilled for instance: {instance}") self.stdout.write(
payment = generate_invoice(instance=instance) f"Payment not fulfilled for instance: {paid_instance.instance}"
)
payment = generate_invoice(instance=paid_instance.instance)
owner = paid_instance.instance.owned_by
ctx = {
"username": owner.username,
"payment": payment,
"link": get_invoice_link(payment=payment),
}
body = render_to_string(
"billing/emails/renew-subscription.txt",
context=ctx,
)
email = owner.email
sender = settings.DEFAULT_FROM_EMAIL
send_mail(
subject="[Gna!] Payment receipt for your Gna! VM",
message=body,
from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py
recipient_list=[email],
)
else: else:
self.stdout.write("No instances available") self.stdout.write("No instances available")

View File

@ -1,6 +1,6 @@
Hello {{ username }}! Hello {{ username }}!
An invoice is generated for your Hostea VM {{ payment.instance_name }}. An invoice is generated for your Gna! VM {{ payment.instance_name }}.
- Configuration: {{payment.instance_configuration_id.name}} - Configuration: {{payment.instance_configuration_id.name}}
- Invoice generated on: {{payment.date.month}}/{{payment.date.day}}/{{payment.date.year}} - Invoice generated on: {{payment.date.month}}/{{payment.date.day}}/{{payment.date.year}}
@ -11,4 +11,4 @@ To pay, please click the link below:
{{ link }} {{ link }}
Cheers, Cheers,
Hostea team Gna! team

View File

@ -1,11 +1,11 @@
Hello {{ username }}! Hello {{ username }}!
This is a receipt for your latest Hostea payment. This is a receipt for your latest Gna! payment.
----------------------------------------------------- -----------------------------------------------------
Hostea Receipt - {{payment.date.month}}/{{payment.date.day}}/{{payment.date.year}} Gna! Receipt - {{payment.date.month}}/{{payment.date.day}}/{{payment.date.year}}
- Instance Name: {{ payment.instance_name }} - Instance Name: {{ payment.instance_name }}
- Configuration: {{payment.instance_configuration_id.name}} - Configuration: {{payment.instance_configuration_id.name}}
@ -19,4 +19,4 @@ To view the receipt online, please see the following link:
We appreciate your business! We appreciate your business!
Cheers, Cheers,
Hostea team Gna! team

View File

@ -0,0 +1,17 @@
Hello {{ username }}!
Your Gna! VM subscription is due for renewal. Please click the link
below to renew your subscription:
{{link}}
-----------------------------------------------------
- Instance Name: {{ payment.instance_name }}
- Configuration: {{payment.instance_configuration_id.name}}
- Total Amount: {{payment.total}} {{payment.currency|upper}}
We appreciate your business!
Cheers,
Gna! team

View File

@ -49,7 +49,7 @@ class BillingTest(TestCase):
def test_payments(self): def test_payments(self):
c = Client() c = Client()
login_util(self, c, "accounts.home") login_util(self, c, "accounts.home")
instance_name = "test_payments" instance_name = "tpayments"
create_instance_util( create_instance_util(
t=self, c=c, instance_name=instance_name, config=self.instance_config[0] t=self, c=c, instance_name=instance_name, config=self.instance_config[0]
) )
@ -95,14 +95,15 @@ class BillingTest(TestCase):
# sent when the invoice is generated and one after payment is made # sent when the invoice is generated and one after payment is made
# #
# So we are first checking for the last email that was sent(receipt) # So we are first checking for the last email that was sent(receipt)
# and then the Gitea instance credentials notification followed by the # and then the Forgejo instance credentials notification followed by the
# invoice generation email. # invoice generation email.
receipt_mail = mail.outbox.pop() receipt_mail = mail.outbox.pop()
print(receipt_mail.body)
self.assertEqual( self.assertEqual(
all( all(
[ [
receipt_mail.to[0] == self.email, receipt_mail.to[0] == self.email,
"This is a receipt for your latest Hostea payment" "This is a receipt for your latest Gna! payment"
in receipt_mail.body, in receipt_mail.body,
] ]
), ),
@ -114,24 +115,13 @@ class BillingTest(TestCase):
all( all(
[ [
instance_notificaiton.to[0] == self.email, instance_notificaiton.to[0] == self.email,
"Congratulations on your new Hostea instance!" "Congratulations on your new Gna! instance!"
in instance_notificaiton.body, in instance_notificaiton.body,
] ]
), ),
True, True,
) )
invoice_generated_mail = mail.outbox.pop()
self.assertEqual(
all(
[
invoice_generated_mail.to[0] == self.email,
"An invoice is generated" in invoice_generated_mail.body,
]
),
True,
)
## payment failure page; no real functionality but user is redirected here ## payment failure page; no real functionality but user is redirected here
# by stripe if payment is successful # by stripe if payment is successful
resp = c.get(reverse("billing.invoice.fail", args=(payment.public_ref,))) resp = c.get(reverse("billing.invoice.fail", args=(payment.public_ref,)))
@ -148,13 +138,51 @@ class GenerateInvoiceCommand(TestCase):
register_util(t=self, username=self.username) register_util(t=self, username=self.username)
create_configurations(t=self) create_configurations(t=self)
@override_settings(
HOSTEA=infra_custom_config(
test_name="test_dont_send_invoices_to_not_created_vms"
)
)
def test_dont_send_invoices_to_not_created_vms(self):
c = Client()
login_util(self, c, "accounts.home")
instance_name = "tnoinvonocrevm"
payload = {"name": instance_name, "configuration": self.instance_config[0].name}
resp = c.post(reverse("dash.instances.new"), payload)
self.assertEqual(resp.status_code, 302)
self.assertEqual(
resp.headers["location"],
reverse("billing.invoice.generate", args=(instance_name,)),
)
stdout = StringIO()
stderr = StringIO()
instance = Instance.objects.get(name=instance_name)
self.assertEqual(payment_fullfilled(instance=instance), False)
prev_len = len(mail.outbox)
# username exists
call_command(
"generate_invoice",
stdout=stdout,
stderr=stderr,
)
out = stdout.getvalue()
print(out)
self.assertEqual(instance_name not in out, True)
@override_settings( @override_settings(
HOSTEA=infra_custom_config(test_name="test_generate_invoice_cmd") HOSTEA=infra_custom_config(test_name="test_generate_invoice_cmd")
) )
def test_cmd(self): def test_cmd(self):
c = Client() c = Client()
login_util(self, c, "accounts.home") login_util(self, c, "accounts.home")
instance_name = "test_generate_invoice_cmd" instance_name = "tgeninvmd"
create_instance_util( create_instance_util(
t=self, c=c, instance_name=instance_name, config=self.instance_config[0] t=self, c=c, instance_name=instance_name, config=self.instance_config[0]
) )

View File

@ -98,27 +98,4 @@ def generate_invoice(instance: Instance) -> Payment:
instance=instance, instance=instance,
) )
invoice_link = get_invoice_link(payment=payment)
ctx = {
"username": instance.owned_by.username,
"link": invoice_link,
"payment": payment,
}
body = render_to_string(
"billing/emails/payment-notification.txt",
context=ctx,
)
email = instance.owned_by.email
sender = settings.DEFAULT_FROM_EMAIL
send_mail(
subject="[Hostea] An invoice is generated for your Hostea VM",
message=body,
from_email=f"No reply Hostea<{sender}>", # TODO read from settings.py
recipient_list=[email],
)
return payment return payment

View File

@ -128,9 +128,9 @@ def payment_success(request, payment_public_id):
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Payment receipt your Hostea VM", subject="[Gna!] Payment receipt for your Gna! VM",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", # TODO read from settings.py from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py
recipient_list=[email], recipient_list=[email],
) )

View File

@ -127,6 +127,10 @@ header {
text-decoration: underline; text-decoration: underline;
} }
.nav__logo-img {
height: 48px;
}
.nav__toggle { .nav__toggle {
display: none; display: none;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 838 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 912 B

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 961 B

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 711 B

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 829 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
common-static/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -4,7 +4,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="stylesheet" href="{% static 'css/main.css' %}" /> <link rel="stylesheet" href="{% static 'css/main.css' %}" />
<title>{{ title }}| Hostea Dashbaord</title> <title>{{ title }}| Gna! Dashboard</title>
{% include "common/components/meta.html" %} {% include "common/components/meta.html" %}
</head> </head>
<body> <body>

View File

@ -1,36 +1,41 @@
{% load static %} {% load static %}
<nav class="nav__container"> <nav class="nav__container">
<input type="checkbox" class="nav__toggle" id="nav__toggle" /> <input type="checkbox" class="nav__toggle" id="nav__toggle" />
<div class="nav__header"> <div class="nav__header">
<a class="nav__logo-container" href="https://hostea.org"> <a class="nav__logo-container" href="https://gna.org">
<img <img alt="Gna! logo" class="nav__logo-img" src="{% static 'img/logo.png' %}" />
src="{% static 'img/android-icon-48x48.png' %}" </a>
alt="Hostea logo" <label class="nav__hamburger-menu" for="nav__toggle">
/> <span class="nav__hamburger-inner"></span>
<p class="nav__home-btn">ostea</p> </label>
</a> </div>
<label class="nav__hamburger-menu" for="nav__toggle">
<span class="nav__hamburger-inner"></span>
</label>
</div>
<div class="nav__spacer"></div> <div class="nav__spacer"></div>
<div class="nav__link-group"> <div class="nav__link-group">
<div class="nav__link-container"> <div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{% url 'dash.instances.new' %}" <a
>Add Instance</a class="nav__link"
> rel="noreferrer"
</div> href="{% url 'dash.instances.new' %}"
<div class="nav__link-container"> >Add Instance</a
<a class="nav__link" rel="noreferrer" href="{% url 'support.home' %}" >
>Support</a </div>
> <div class="nav__link-container">
</div> <a
<div class="nav__link-container"> class="nav__link"
<a class="nav__link" rel="noreferrer" href="{% url 'accounts.logout' %}" rel="noreferrer"
>Logout</a href="{% url 'support.home' %}"
> >Support</a
</div> >
</div> </div>
<div class="nav__link-container">
<a
class="nav__link"
rel="noreferrer"
href="{% url 'accounts.logout' %}"
>Logout</a
>
</div>
</div>
</nav> </nav>

View File

@ -12,7 +12,7 @@
</ul> </ul>
<p>Created On: {{ instance.created_at }}</p> <p>Created On: {{ instance.created_at }}</p>
<p><a href="{{gitea_uri}}">Gitea Instance</a>|<a href="{{woodpecker}}">Woodpecker CI</a></p> <p><a href="{{forgejo_uri}}">Forgejo Instance</a>|<a href="{{woodpecker}}">Woodpecker CI</a></p>
<form <form
action="{% url 'dash.instances.delete' name=instance.name %}" action="{% url 'dash.instances.delete' name=instance.name %}"

View File

@ -30,6 +30,7 @@ from payments import get_payment_model, RedirectNeeded, PaymentStatus
from accounts.tests import login_util, register_util from accounts.tests import login_util, register_util
from .models import InstanceConfiguration, Instance from .models import InstanceConfiguration, Instance
from .utils import create_instance, sanitize_vm_name, VmErrors, VmException
def create_configurations(t: TestCase): def create_configurations(t: TestCase):
@ -170,7 +171,7 @@ class InstancesConfig(TestCase):
""" """
Expects InstancesConfig titled "s1-2", "s1-4" and "s1-8" Expects InstancesConfig titled "s1-2", "s1-4" and "s1-8"
ref: https://gitea.hostea.org/Hostea/july-mvp/issues/10#issuecomment-639 ref: https://forgejo.gna.org/Hostea/july-mvp/issues/10#issuecomment-639
""" """
self.assertEqual( self.assertEqual(
InstanceConfiguration.objects.filter( InstanceConfiguration.objects.filter(
@ -197,6 +198,30 @@ class CreateInstance(TestCase):
register_util(t=self, username="createinstance_user") register_util(t=self, username="createinstance_user")
create_configurations(t=self) create_configurations(t=self)
def test_sanitize_vm_name(self):
self.assertEqual(sanitize_vm_name(vm_name="LOWERname"), "lowername")
with self.assertRaises(VmException):
sanitize_vm_name(vm_name="12345452131324234234234234")
with self.assertRaises(VmException):
sanitize_vm_name(vm_name="122342$#34234")
@override_settings(
HOSTEA=infra_custom_config(test_name="test_create_instance_util")
)
def test_create_instance_util(self):
configuration = self.instance_config[0].name
with self.assertRaises(VmException):
create_instance(
vm_name="12345452131324234234234234",
configuration_name=configuration,
user=self.user,
)
@override_settings( @override_settings(
HOSTEA=infra_custom_config(test_name="test_create_instance_renders") HOSTEA=infra_custom_config(test_name="test_create_instance_renders")
) )
@ -214,14 +239,14 @@ class CreateInstance(TestCase):
self.assertEqual(str.encode(test) in resp.content, True) self.assertEqual(str.encode(test) in resp.content, True)
# create instance # create instance
instance_name = "testirenrs"
payload = { payload = {
"name": "test_create_instance_renders", "name": instance_name,
"configuration": self.instance_config[0].name, "configuration": self.instance_config[0].name,
} }
self.assertEqual(Instance.objects.filter(name=payload["name"]).exists(), False) self.assertEqual(Instance.objects.filter(name=payload["name"]).exists(), False)
instance_name = "test_create_instance_renders"
create_instance_util( create_instance_util(
t=self, c=c, instance_name=instance_name, config=self.instance_config[0] t=self, c=c, instance_name=instance_name, config=self.instance_config[0]
) )

View File

@ -23,6 +23,8 @@ from .models import Instance, InstanceConfiguration
@unique @unique
class VmErrors(Enum): class VmErrors(Enum):
NAME_EXISTS = "Instance name exists, please try again with a different name" NAME_EXISTS = "Instance name exists, please try again with a different name"
ILLEGAL_NAME = "Only alphanumeric characters are allowed in instance name"
NAME_TOO_LONG = "Instance name must be less than 20 characters"
NO_CONFIG = "Configuration doesn't exist, please try again." NO_CONFIG = "Configuration doesn't exist, please try again."
def __str__(self) -> str: def __str__(self) -> str:
@ -41,13 +43,30 @@ class VmException(Exception):
return self.error return self.error
def sanitize_vm_name(vm_name: str) -> str:
"""
Sanity checks and normalization of the vm name
"""
vm_name = vm_name.lower()
if len(vm_name) > 20:
raise VmException(code=VmErrors.NAME_TOO_LONG)
if not str.isalnum(vm_name):
raise VmException(code=VmErrors.ILLEGAL_NAME)
if Instance.objects.filter(name=vm_name).exists():
raise VmException(code=VmErrors.NAME_EXISTS)
return vm_name
def create_instance(vm_name: str, configuration_name: str, user: User) -> Instance: def create_instance(vm_name: str, configuration_name: str, user: User) -> Instance:
""" """
Create instance view Create instance view
""" """
if Instance.objects.filter(name=vm_name).exists(): vm_name = sanitize_vm_name(vm_name)
raise VmException(code=VmErrors.NAME_EXISTS)
if not InstanceConfiguration.objects.filter(name=configuration_name).exists(): if not InstanceConfiguration.objects.filter(name=configuration_name).exists():
raise VmException(code=VmErrors.NO_CONFIG) raise VmException(code=VmErrors.NO_CONFIG)
@ -70,7 +89,7 @@ def footer_ctx():
"link": settings.HOSTEA["SOURCE_CODE"], "link": settings.HOSTEA["SOURCE_CODE"],
} }
else: else:
link = "https://gitea.hostea.org/Hostea/dashboard" link = "https://forgejo.gna.org/Hostea/dashboard"
source_code = {"text": "Source Code", "link": link} source_code = {"text": "Source Code", "link": link}
try: try:
r = Repo(".") r = Repo(".")

View File

@ -89,10 +89,7 @@ def create_instance(request):
return redirect(reverse("billing.invoice.generate", args=(instance.name,))) return redirect(reverse("billing.invoice.generate", args=(instance.name,)))
except VmException as e: except VmException as e:
ctx = get_ctx() ctx = get_ctx()
if e.code == VmErrors.NAME_EXISTS: reason = e.code.value
reason = ("Instance name exists, please try again with a different name",)
elif e.code == VmErrors.NO_CONFIG:
reason = "Configuration doesn't exist, please try again."
ctx["error"] = { ctx["error"] = {
"title": "Can't create instance", "title": "Can't create instance",
@ -120,12 +117,12 @@ def view_instance(request, name: str):
instance = get_object_or_404(Instance, owned_by=user, name=name) instance = get_object_or_404(Instance, owned_by=user, name=name)
ctx = default_ctx(title=PAGE_TITLE, username=user.username) ctx = default_ctx(title=PAGE_TITLE, username=user.username)
instance.configuration = instance.configuration_id instance.configuration = instance.configuration_id
gitea_uri = Infra.get_gitea_uri(instance=instance) forgejo_uri = Infra.get_forgejo_uri(instance=instance)
woodpecker = Infra.get_woodpecker_uri(instance=instance) woodpecker = Infra.get_woodpecker_uri(instance=instance)
ctx["instance"] = instance ctx["instance"] = instance
ctx["woodpecker"] = woodpecker ctx["woodpecker"] = woodpecker
ctx["gitea_uri"] = gitea_uri ctx["forgejo_uri"] = forgejo_uri
return render(request, "dash/instances/view/index.html", context=ctx) return render(request, "dash/instances/view/index.html", context=ctx)

View File

@ -44,8 +44,8 @@ PAYMENT_VARIANTS = {
"stripe": ( "stripe": (
"payments.stripe.StripeProvider", # please don't change this "payments.stripe.StripeProvider", # please don't change this
{ {
"secret_key": env.get_value("STRIPE_SECRET_KEY"), "secret_key": env.get_value("STRIPE_SECRET_KEY", default="UNSET"),
"public_key": env.get_value("STRIPE_PUBLIC_KEY"), "public_key": env.get_value("STRIPE_PUBLIC_KEY", default="UNSET"),
}, },
) )
} }
@ -54,19 +54,19 @@ PAYMENT_VARIANTS = {
### Dashbaord specific configuration options ### Dashbaord specific configuration options
HOSTEA = { HOSTEA = {
"SOURCE_CODE": "https://gitea.hostea.org/Hostea/dashboard", "SOURCE_CODE": "https://forgejo.gna.org/Hostea/dashboard",
"INSTANCE_MAINTAINER_CONTACT": "contact@hostea.example.org", "INSTANCE_MAINTAINER_CONTACT": "contact@gna.example.org",
"ACCOUNTS": { "ACCOUNTS": {
"MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds "MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds
"SUDO_TTL": 60 * 5, "SUDO_TTL": 60 * 5,
}, },
"META": { "META": {
"GITEA_INSTANCE": env.get_value( "FORGEJO_INSTANCE": env.get_value(
"HOSTEA_META_GITEA_INSTANCE" "HOSTEA_META_FORGEJO_INSTANCE"
), # meta Gitea insatnce ), # meta Forgejo insatnce
"GITEA_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance "FORGEJO_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance
# Repository dedicated for handling support # Repository dedicated for handling support
# ref: https://gitea.hostea.org/Hostea/july-mvp/issues/17 # ref: https://forgejo.gna.org/Hostea/july-mvp/issues/17
"SUPPORT_REPOSITORY": "support", "SUPPORT_REPOSITORY": "support",
}, },
"INFRA": { "INFRA": {
@ -78,14 +78,14 @@ HOSTEA = {
# SSH key that can push to the Git repository remote mentioned above # SSH key that can push to the Git repository remote mentioned above
"SSH_KEY": env.get_value("HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY"), "SSH_KEY": env.get_value("HOSTEA_INFRA_HOSTEA_REPO_SSH_KEY"),
}, },
"HOSTEA_DOMAIN": "hostea.org", # domain at which Hostea VMs will be spun up "HOSTEA_DOMAIN": "gna.org", # domain at which Hostea VMs will be spun up
}, },
} }
# Please see EMAIL_* configuration options: # Please see EMAIL_* configuration options:
# https://docs.djangoproject.com/en/4.1/ref/settings/#email-host # https://docs.djangoproject.com/en/4.1/ref/settings/#email-host
EMAIL_CONFIG = env.email("EMAIL_URL", default="smtp://admin:password@localhost:10025") EMAIL_CONFIG = env.email("EMAIL_URL", default="smtp://admin:password@localhost:10025")
DEFAULT_FROM_EMAIL = "no-reply@hostea.org" DEFAULT_FROM_EMAIL = "no-reply@gna.org"
vars().update(EMAIL_CONFIG) vars().update(EMAIL_CONFIG)

View File

@ -53,17 +53,17 @@ PAYMENT_VARIANTS = {
### Dashbaord specific configuration options ### Dashbaord specific configuration options
HOSTEA = { HOSTEA = {
"SOURCE_CODE": "https://gitea.hostea.org/Hostea/dashboard", "SOURCE_CODE": "https://forgejo.gna.org/Hostea/dashboard",
"INSTANCE_MAINTAINER_CONTACT": "contact@hostea.example.org", "INSTANCE_MAINTAINER_CONTACT": "contact@gna.example.org",
"ACCOUNTS": { "ACCOUNTS": {
"MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds "MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds
"SUDO_TTL": 60 * 5, "SUDO_TTL": 60 * 5,
}, },
"META": { "META": {
"GITEA_INSTANCE": "https://gitea.hostea.org", # meta Gitea insatnce "FORGEJO_INSTANCE": "https://forgejo.gna.org", # meta Forgejo insatnce
"GITEA_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance "FORGEJO_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance
# Repository dedicated for handling support # Repository dedicated for handling support
# ref: https://gitea.hostea.org/Hostea/july-mvp/issues/17 # ref: https://forgejo.gna.org/Hostea/july-mvp/issues/17
"SUPPORT_REPOSITORY": "support", "SUPPORT_REPOSITORY": "support",
}, },
"INFRA": { "INFRA": {
@ -87,4 +87,4 @@ EMAIL_USE_SSL = False
EMAIL_PORT = 10025 EMAIL_PORT = 10025
EMAIL_HOST_USER = "admin" EMAIL_HOST_USER = "admin"
EMAIL_HOST_PASSWORD = "password" EMAIL_HOST_PASSWORD = "password"
DEFAULT_FROM_EMAIL = "no-reply@hostea.org" DEFAULT_FROM_EMAIL = "no-reply@gna.org"

View File

@ -171,18 +171,18 @@ PAYMENT_VARIANTS = {
### Dashbaord specific configuration options ### Dashbaord specific configuration options
HOSTEA = { HOSTEA = {
"SOURCE_CODE": "https://gitea.hostea.org/Hostea/dashboard", "SOURCE_CODE": "https://forgejo.gna.org/Hostea/dashboard",
"RESTRICT_NEW_INTEGRATION_INSTALLATION": True, "RESTRICT_NEW_INTEGRATION_INSTALLATION": True,
"INSTANCE_MAINTAINER_CONTACT": "contact@hostea.example.org", "INSTANCE_MAINTAINER_CONTACT": "contact@gna.example.org",
"ACCOUNTS": { "ACCOUNTS": {
"MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds "MAX_VERIFICATION_TOLERANCE_PERIOD": 60 * 60 * 24, # in seconds
"SUDO_TTL": 60 * 5, "SUDO_TTL": 60 * 5,
}, },
"META": { "META": {
"GITEA_INSTANCE": "http://localhost:3000", # meta Gitea insatnce "FORGEJO_INSTANCE": "http://localhost:3000", # meta Forgejo insatnce
"GITEA_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance "FORGEJO_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance
# Repository dedicated for handling support # Repository dedicated for handling support
# ref: https://gitea.hostea.org/Hostea/july-mvp/issues/17 # ref: https://forgejo.gna.org/Hostea/july-mvp/issues/17
"SUPPORT_REPOSITORY": "support", "SUPPORT_REPOSITORY": "support",
}, },
"INFRA": { "INFRA": {
@ -194,7 +194,7 @@ HOSTEA = {
# SSH key that can push to the Git repository remote mentioned above # SSH key that can push to the Git repository remote mentioned above
"SSH_KEY": "/srv/hostea/deploy", "SSH_KEY": "/srv/hostea/deploy",
}, },
"HOSTEA_DOMAIN": "vm.hostea.org", # domain at which Hostea VMs will be spun up "HOSTEA_DOMAIN": "vm.gna.org", # domain at which Hostea VMs will be spun up
}, },
} }
@ -206,7 +206,7 @@ EMAIL_USE_SSL = False
EMAIL_PORT = 10025 EMAIL_PORT = 10025
EMAIL_HOST_USER = "admin" EMAIL_HOST_USER = "admin"
EMAIL_HOST_PASSWORD = "password" EMAIL_HOST_PASSWORD = "password"
DEFAULT_FROM_EMAIL: "no-reply@hostea.org" DEFAULT_FROM_EMAIL: "no-reply@gna.org"
try: try:
from dashboard.local_settings import * from dashboard.local_settings import *

View File

@ -1,23 +1,23 @@
version: "3" version: "3"
#networks: #networks:
# hostea-dash-gitea: # hostea-dash-forgejo:
# external: false # external: false
# hostea-dash-smtp: # hostea-dash-smtp:
# external: false # external: false
services: services:
gitea: forgejo:
image: gitea/gitea:1.16.5 image: codeberg.org/forgejo/forgejo:1.18.0-1
container_name: hostea-dash-gitea container_name: hostea-dash-forgejo
network_mode: host network_mode: host
environment: environment:
- USER_UID=1000 - USER_UID=1000
- USER_GID=1000 - USER_GID=1000
restart: always restart: always
#networks: #networks:
# - hostea-dash-gitea # - hostea-dash-forgejo
volumes: volumes:
- /etc/timezone:/etc/timezone:ro - /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro

View File

@ -15,7 +15,7 @@
1. Clone the project 1. Clone the project
```bash ```bash
git clone https://gitea.hostea.org/Hostea/dashboard.git && cd dashboard git clone https://forgejo.gna.org/Hostea/dashboard.git && cd dashboard
``` ```
2. Create `virtualenv` and activate environment 2. Create `virtualenv` and activate environment

View File

@ -44,8 +44,8 @@ hence the current redundancy in configuration and cronjob duration.
## Support Platform Integration ## Support Platform Integration
Hostea Dashbaord delegates support to Hostea's meta Gitea instance, as Hostea Dashbaord delegates support to Hostea's meta Forgejo instance, as
discussed [here](https://gitea.hostea.org/Hostea/july-mvp/issues/17). discussed [here](https://forgejo.gna.org/Hostea/july-mvp/issues/17).
To configure support platform integration , please set the following To configure support platform integration , please set the following
attributes in `settings.py`: attributes in `settings.py`:
@ -55,10 +55,10 @@ HOSTEA = {
# <--snip---> # <--snip--->
"META": { "META": {
# <--snip---> # <--snip--->
"GITEA_INSTANCE": "https://gitea.hostea.org", # meta Gitea insatnce "FORGEJO_INSTANCE": "https://forgejo.gna.org", # meta Forgejo insatnce
"GITEA_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance "FORGEJO_ORG_NAME": "Hostea", # Organisation name on Hostea meta instance
# Repository dedicated for handling support # Repository dedicated for handling support
# ref: https://gitea.hostea.org/Hostea/july-mvp/issues/17 # ref: https://forgejo.gna.org/Hostea/july-mvp/issues/17
"SUPPORT_REPOSITORY": "support", "SUPPORT_REPOSITORY": "support",
}, },
} }

View File

@ -93,9 +93,9 @@ class Command(BaseCommand):
instance = create_instance( instance = create_instance(
vm_name=vm_name, configuration_name=size, user=user vm_name=vm_name, configuration_name=size, user=user
) )
(gitea_password, _commit) = create_vm_if_not_exists(instance) (forgejo_password, _commit) = create_vm_if_not_exists(instance)
print("Instance created") print("Instance created")
print(f"Gitea admin password: {gitea_password}") print(f"Forgejo admin password: {forgejo_password}")
except VmException as e: except VmException as e:
if e.code == VmErrors.NAME_EXISTS: if e.code == VmErrors.NAME_EXISTS:
instance = Instance.objects.get(name=vm_name) instance = Instance.objects.get(name=vm_name)
@ -104,9 +104,9 @@ class Command(BaseCommand):
name=size name=size
) )
instance.save() instance.save()
(gitea_password, _commit) = create_vm_if_not_exists(instance) (forgejo_password, _commit) = create_vm_if_not_exists(instance)
print("Instance created") print("Instance created")
print(f"Gitea admin password: {gitea_password}") print(f"Forgejo admin password: {forgejo_password}")
else: else:
self.stderr.write(self.style.ERROR(f"error: {str(e)}")) self.stderr.write(self.style.ERROR(f"error: {str(e)}"))

View File

@ -0,0 +1,18 @@
Hello {{ username }},
Congratulations on your new Gna! instance!
Your Gna! instance is being prepared, you will receive an email
notification when it is ready.
You can use the following credentials to log into an admin account on
your new Gna! Forgejo instance. Great powers come with great
responsibilities, so use the admin credentials wisely. When in doubt,
consult the Forgejo docs or contact support!
- username : root
- password: {{ forgejo_password }}
- Forgejo {{ forgejo_uri }}
Cheers,
Gna! team

View File

@ -1,18 +0,0 @@
Hello {{ username }},
Congratulations on your new Hostea instance!
Your Hostea instance is being prepared, you will receive an email
notification when it is ready.
You can use the following credentials to log into an admin account on
your new Hostea Gitea instance. Great powers come with great
responsibilities, so use the admin credentials wisely. When in doubt,
consult the Gitea docs or contact support!
- username : root
- password: {{ gitea_password }}
- Gitea {{ gitea_uri }}
Cheers,
Hostea team

View File

@ -1,11 +1,11 @@
Hello {{ username }}!, Hello {{ username }}!,
The deployment job has run to completion and your Hostea instance is now online! The deployment job has run to completion and your Gna! instance is now online!
Credentials to admin account was sent in an earlier email, please contact Credentials to admin account was sent in an earlier email, please contact
support if didn't receive it. support if didn't receive it.
Gitea: {{ gitea_uri }} Forgejo: {{ forgejo_uri }}
Woodpecker CI: {{ woodpecker_uri }} Woodpecker CI: {{ woodpecker_uri }}
Cheers, Cheers,
Hostea team Gna! team

View File

@ -0,0 +1,10 @@
Hello {{ username }}!,
A customer has purchased a new instance. Please find the details below:
Forgejo: {{ forgejo_uri }}
Woodpecker CI: {{ woodpecker_uri }}
Cheers,
Gna! team

View File

@ -1,11 +1,11 @@
{% extends 'dash/common/base.html' %} {% block dash %} {% extends 'dash/common/base.html' %} {% block dash %}
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
<h2>Gitea Admin Credentials</h2> <h2>Forgejo Admin Credentials</h2>
<ul> <ul>
<li><b>Username:</b> root</li> <li><b>Username:</b> root</li>
<li><b>Password:</b> {{ gitea_password }}</li> <li><b>Password:</b> {{ forgejo_password }}</li>
</ul> </ul>
{% endblock %} {% endblock %}

View File

@ -1,2 +1,2 @@
enough --domain $domain host create {{subdomain}}-host enough --domain $domain host create {{subdomain}}-host
enough --domain $domain service create --host {{subdomain}}-host gitea enough --domain $domain service create --host {{subdomain}}-host forgejo

View File

@ -2,49 +2,49 @@
# #
####################################### #######################################
# #
# Public hostname of the Gitea instance # Public hostname of the Forgejo instance
# #
# #
gitea_host: "{{ subdomain }}.{{ '{' }}{{ '{' }} domain {{ '}' }}{{ '}' }}" forgejo_host: "{{ subdomain }}.{{ '{' }}{{ '{' }} domain {{ '}' }}{{ '}' }}"
# #
####################################### #######################################
# #
# Mailer from # Mailer from
# #
# #
gitea_mailer_from: "noreply@{{ '{' }}{{ '{' }} domain {{ '}' }}{{ '}' }}" forgejo_mailer_from: "noreply@{{ '{' }}{{ '{' }} domain {{ '}' }}{{ '}' }}"
# #
####################################### #######################################
# #
# SSH port of the Gitea instance # SSH port of the Forgejo instance
# #
# #
gitea_ssh_port: "22" forgejo_ssh_port: "22"
# #
####################################### #######################################
# #
# Gitea version # Forgejo version
# #
# #
gitea_version: "1.16.8" #forgejo_version: "1.18.0-1"
# #
####################################### #######################################
# #
# Admin user name # Admin user name
# #
gitea_user: root forgejo_user: root
# #
####################################### #######################################
# #
# Admin user password # Admin user password
# #
gitea_password: "{{ gitea_password }}" forgejo_password: "{{ forgejo_password }}"
# #
####################################### #######################################
# #
# Admin user email # Admin user email
# #
gitea_email: "{{ gitea_email }}" forgejo_email: "{{ forgejo_email }}"
# #
####################################### #######################################
# #
@ -60,9 +60,9 @@ woodpecker_host: "{{ '{' }}{{ '{' }} woodpecker_hostname {{ '}' }}{{ '}' }}.{{ '
# #
####################################### #######################################
# #
# Gitea users with admin rights on woodpecker # Forgejo users with admin rights on woodpecker
# #
woodpecker_admins: "{{ '{' }}{{ '{' }} gitea_user {{ '}' }}{{ '}' }}" woodpecker_admins: "{{ '{' }}{{ '{' }} forgejo_user {{ '}' }}{{ '}' }}"
# #
####################################### #######################################
# #

View File

@ -1,4 +1,4 @@
gitea-service-group: forgejo-service-group:
hosts: hosts:
{{ subdomain }}-host: {{ subdomain }}-host:
ansible_port: 2222 ansible_port: 2222

View File

@ -17,6 +17,7 @@ from io import StringIO
from django.test import TestCase, Client, override_settings from django.test import TestCase, Client, override_settings
from django.core.management import call_command from django.core.management import call_command
from django.core import mail
from dash.models import Instance, InstanceConfiguration from dash.models import Instance, InstanceConfiguration
from accounts.tests import register_util, login_util from accounts.tests import register_util, login_util
@ -37,6 +38,8 @@ class InfraUtilTest(TestCase):
def setUp(self): def setUp(self):
self.username = "infrautil_user" self.username = "infrautil_user"
register_util(t=self, username=self.username) register_util(t=self, username=self.username)
self.user.is_staff = True
self.user.save()
create_configurations(t=self) create_configurations(t=self)
# @override_settings(HOSTEA=infra_custom_config(test_name="test_path_util")) # @override_settings(HOSTEA=infra_custom_config(test_name="test_path_util"))
@ -51,8 +54,8 @@ class InfraUtilTest(TestCase):
# ) # )
# #
# self.assertEqual( # self.assertEqual(
# base.joinpath(f"inventory/host_vars/{subdomain}-host/gitea.yml"), # base.joinpath(f"inventory/host_vars/{subdomain}-host/forgejo.yml"),
# infra._gitea_path(subdomain=subdomain), # infra._forgejo_path(subdomain=subdomain),
# ) # )
# #
# self.assertEqual( # self.assertEqual(
@ -153,7 +156,7 @@ class InfraUtilTest(TestCase):
# call_command("vm", "delete", subdomain) # call_command("vm", "delete", subdomain)
# #
# def test_worker(self): # def test_worker(self):
# subdomain = "gitea" # yes, gitea.hostea.org exists. will use it till I # subdomain = "forgejo" # yes, forgejo.hostea.org exists. will use it till I
# # figure out how to use requests_mock within django # # figure out how to use requests_mock within django
# c = Client() # c = Client()
# login_util(self, c, "accounts.home") # login_util(self, c, "accounts.home")
@ -163,8 +166,8 @@ class InfraUtilTest(TestCase):
# #
# instance = Instance.objects.get(name=subdomain) # instance = Instance.objects.get(name=subdomain)
# job = Job.objects.create(instance=instance, job_type=JobType.PING) # job = Job.objects.create(instance=instance, job_type=JobType.PING)
# gitea_uri = Infra.get_gitea_uri(instance=instance) # forgejo_uri = Infra.get_forgejo_uri(instance=instance)
# print(f"mocking {gitea_uri}") # print(f"mocking {forgejo_uri}")
# #
# w = Worker(job=job) # w = Worker(job=job)
# w.start() # w.start()
@ -181,11 +184,11 @@ class InfraUtilTest(TestCase):
Test if the dashboard generates invoices for a VM crated with a name Test if the dashboard generates invoices for a VM crated with a name
matching a VM name that was deleted that existed. matching a VM name that was deleted that existed.
ref: https://gitea.hostea.org/Hostea/dashboard/issues/38#issuecomment-1162 ref: https://forgejo.hostea.org/Hostea/dashboard/issues/38#issuecomment-1162
""" """
c = Client() c = Client()
login_util(self, c, "accounts.home") login_util(self, c, "accounts.home")
instance_name = "test_vm_delete_payments" instance_name = "trmpayments"
infra = Infra() infra = Infra()
@ -226,3 +229,18 @@ class InfraUtilTest(TestCase):
print(out) print(out)
self.assertEqual(instance_name in out, True) self.assertEqual(instance_name in out, True)
self.assertEqual(f"Payment not fulfilled for instance: {instance}" in out, True) self.assertEqual(f"Payment not fulfilled for instance: {instance}" in out, True)
staff_notification = None
for m in mail.outbox:
if "New instance alert" in m.subject:
staff_notification = m
break
self.assertEqual(staff_notification.to[0], self.email)
self.assertEqual(
"[Gna!] New instance alert" in staff_notification.subject, True
)
self.assertEqual(
"A customer has purchased a new instance. Please find the details below:"
in staff_notification.body,
True,
)

View File

@ -24,6 +24,7 @@ from time import sleep
from django.utils.crypto import get_random_string from django.utils.crypto import get_random_string
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.contrib.auth import get_user_model
from django.core.mail import send_mail from django.core.mail import send_mail
from django.conf import settings from django.conf import settings
from payments import get_payment_model from payments import get_payment_model
@ -42,12 +43,12 @@ class Worker(Thread):
super().__init__() super().__init__()
def run(self): def run(self):
gitea_uri = Infra.get_gitea_uri(instance=self.job.instance) forgejo_uri = Infra.get_forgejo_uri(instance=self.job.instance)
woodpecker = Infra.get_woodpecker_uri(instance=self.job.instance) woodpecker = Infra.get_woodpecker_uri(instance=self.job.instance)
while True: while True:
try: try:
print(f"[ping] Trying to reach {gitea_uri}") print(f"[ping] Trying to reach {forgejo_uri}")
resp = requests.get(gitea_uri) resp = requests.get(forgejo_uri)
if resp.status_code == 200: if resp.status_code == 200:
break break
except Exception: except Exception:
@ -59,7 +60,7 @@ class Worker(Thread):
email = job.instance.owned_by.email email = job.instance.owned_by.email
ctx = { ctx = {
"gitea_uri": gitea_uri, "forgejo_uri": forgejo_uri,
"woodpecker_uri": woodpecker, "woodpecker_uri": woodpecker,
"username": job.instance.owned_by.username, "username": job.instance.owned_by.username,
} }
@ -71,9 +72,9 @@ class Worker(Thread):
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Your Hostea instance is now online!", subject="[Gna!] Your Gna! instance is now online!",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", # TODO read from settings.py from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py
recipient_list=[email], recipient_list=[email],
) )
job.delete() job.delete()
@ -81,20 +82,49 @@ class Worker(Thread):
def create_vm_if_not_exists(instance: Instance) -> (str, str): def create_vm_if_not_exists(instance: Instance) -> (str, str):
""" """
Create VM utility. Gitea password is returned Create VM utility. Forgejo password is returned
""" """
def notify_staff(instance: Instance):
infra = Infra()
User = get_user_model()
forgejo_uri = Infra.get_forgejo_uri(instance=instance)
woodpecker = Infra.get_woodpecker_uri(instance=instance)
for staff in User.objects.filter(is_staff=True):
ctx = {
"forgejo_uri": forgejo_uri,
"woodpecker_uri": woodpecker,
"username": staff.username,
}
body = render_to_string(
"infrastructure/emails/staff-new-instance-alert.txt",
context=ctx,
)
sender = settings.DEFAULT_FROM_EMAIL
send_mail(
subject="[Gna!] New instance alert",
message=body,
from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py
recipient_list=[staff.email],
)
infra = Infra() infra = Infra()
if not InstanceCreated.objects.filter(instance=instance).exists(): if not InstanceCreated.objects.filter(instance=instance).exists():
(gitea_password, commit) = infra.add_vm(instance=instance) (forgejo_password, commit) = infra.add_vm(instance=instance)
InstanceCreated.objects.create(instance=instance, created=True) InstanceCreated.objects.create(instance=instance, created=True)
notify_staff(instance=instance)
job = Job.objects.create(instance=instance, job_type=str(JobType.PING)) job = Job.objects.create(instance=instance, job_type=str(JobType.PING))
Worker(job=job).start() Worker(job=job).start()
return (gitea_password, commit) return (forgejo_password, commit)
else: else:
if str.strip(infra.get_flavor(instance=instance)) != str.strip( if str.strip(infra.get_flavor(instance=instance)) != str.strip(
infra.translate_size(instance=instance) infra.translate_size(instance=instance)
): ):
# Worker.init_global() # Worker.init_global()
notify_staff(instance=instance)
return infra.add_vm(instance=instance) return infra.add_vm(instance=instance)
return None return None
@ -147,9 +177,9 @@ class Infra:
return self._host_vars_dir(subdomain=subdomain).joinpath("provision.yml") return self._host_vars_dir(subdomain=subdomain).joinpath("provision.yml")
@classmethod @classmethod
def get_gitea_uri(cls, instance: Instance) -> str: def get_forgejo_uri(cls, instance: Instance) -> str:
""" """
Get an instance's Gitea URI Get an instance's Forgejo URI
""" """
base = settings.HOSTEA["INFRA"]["HOSTEA_DOMAIN"] base = settings.HOSTEA["INFRA"]["HOSTEA_DOMAIN"]
return f"https://{instance.name}.{base}" return f"https://{instance.name}.{base}"
@ -164,7 +194,7 @@ class Infra:
@classmethod @classmethod
def get_woodpecker_uri(cls, instance: Instance) -> str: def get_woodpecker_uri(cls, instance: Instance) -> str:
""" """
Get an instance's Gitea URI Get an instance's Forgejo URI
""" """
base = settings.HOSTEA["INFRA"]["HOSTEA_DOMAIN"] base = settings.HOSTEA["INFRA"]["HOSTEA_DOMAIN"]
return f"https://{cls._gen_woodpecker_hostname(instance=instance)}.{base}" return f"https://{cls._gen_woodpecker_hostname(instance=instance)}.{base}"
@ -181,12 +211,12 @@ class Infra:
return config["openstack_flavor"].split("{{ ")[1].split(" }}")[0] return config["openstack_flavor"].split("{{ ")[1].split(" }}")[0]
return None return None
def _gitea_path(self, subdomain: str) -> Path: def _forgejo_path(self, subdomain: str) -> Path:
""" """
utility method: get gitea file for a subdomain utility method: get forgejo file for a subdomain
""" """
return self._host_vars_dir(subdomain=subdomain).joinpath("gitea.yml") return self._host_vars_dir(subdomain=subdomain).joinpath("forgejo.yml")
def _backup_path(self, subdomain: str) -> Path: def _backup_path(self, subdomain: str) -> Path:
""" """
@ -254,7 +284,7 @@ class Infra:
""" """
Add new VM to infrastructure repository Add new VM to infrastructure repository
The gitea user password is returned The forgejo user password is returned
""" """
subdomain = instance.name subdomain = instance.name
@ -268,22 +298,22 @@ class Infra:
os.makedirs(hostscript_path) os.makedirs(hostscript_path)
woodpecker_agent_secret = get_random_string(64) woodpecker_agent_secret = get_random_string(64)
gitea_password = get_random_string(20) forgejo_password = get_random_string(20)
ctx = { ctx = {
"woodpecker_agent_secret": woodpecker_agent_secret, "woodpecker_agent_secret": woodpecker_agent_secret,
"woodpecker_hostname": self._gen_woodpecker_hostname(instance=instance), "woodpecker_hostname": self._gen_woodpecker_hostname(instance=instance),
"woodpecker_admins": f"{instance.owned_by.username}", "woodpecker_admins": f"{instance.owned_by.username}",
"gitea_email": instance.owned_by.email, "forgejo_email": instance.owned_by.email,
"gitea_password": gitea_password, "forgejo_password": forgejo_password,
"subdomain": subdomain, "subdomain": subdomain,
} }
gitea = self._gitea_path(subdomain) forgejo = self._forgejo_path(subdomain)
with open(gitea, "w+", encoding="utf-8") as f: with open(forgejo, "w+", encoding="utf-8") as f:
f.write( f.write(
render_to_string( render_to_string(
"infrastructure/yml/gitea.yml", "infrastructure/yml/forgejo.yml",
context=ctx, context=ctx,
) )
) )
@ -327,7 +357,7 @@ class Infra:
) )
commit = self._push(f"add vm {subdomain}") commit = self._push(f"add vm {subdomain}")
return (gitea_password, commit) return (forgejo_password, commit)
def remove_vm(self, instance: Instance): def remove_vm(self, instance: Instance):
""" """

View File

@ -53,25 +53,25 @@ def create_instance(request, instance_name: str):
res = create_vm_if_not_exists(instance=instance) res = create_vm_if_not_exists(instance=instance)
if res is not None: if res is not None:
(gitea_password, commit) = res (forgejo_password, commit) = res
ctx = { ctx = {
"username": request.user.username, "username": request.user.username,
"gitea_password": gitea_password, "forgejo_password": forgejo_password,
"gitea_uri": Infra.get_gitea_uri(instance=instance), "forgejo_uri": Infra.get_forgejo_uri(instance=instance),
} }
body = render_to_string( body = render_to_string(
"infrastructure/emails/gitea-creds.txt", "infrastructure/emails/forgejo-creds.txt",
context=ctx, context=ctx,
) )
sender = settings.DEFAULT_FROM_EMAIL sender = settings.DEFAULT_FROM_EMAIL
send_mail( send_mail(
subject="[Hostea] Gitea admin credentials", subject="[Gna!] Forgejo admin credentials",
message=body, message=body,
from_email=f"No reply Hostea<{sender}>", # TODO read from settings.py from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py
recipient_list=[request.user.email], recipient_list=[request.user.email],
) )

View File

@ -16,7 +16,7 @@ init() {
sleep 5 sleep 5
# wait_for_env # wait_for_env
fi fi
gitea_root forgejo_root
support_repo_init support_repo_init
fleet_repo_init fleet_repo_init
} }

View File

@ -3,10 +3,10 @@ import argparse
from requests import Session from requests import Session
def gitea_from_args(args, c: Session): def forgejo_from_args(args, c: Session):
from .gitea import Gitea from .forgejo import Forgejo
return Gitea( return Forgejo(
host=args.host, host=args.host,
username=args.username, username=args.username,
password=args.password, password=args.password,
@ -15,7 +15,7 @@ def gitea_from_args(args, c: Session):
) )
class Gitea: class Forgejo:
def __init__(self, parser, c: Session): def __init__(self, parser, c: Session):
self.c = c self.c = c
self.parser = parser self.parser = parser
@ -29,56 +29,56 @@ class Gitea:
def __add_credentials_parser(self, parser): def __add_credentials_parser(self, parser):
group = parser.add_argument_group("credentials", "User credentials") group = parser.add_argument_group("credentials", "User credentials")
group.add_argument("username", type=str, help="Gitea user's username") group.add_argument("username", type=str, help="Forgejo user's username")
group.add_argument("password", type=str, help="Gitea user's password") group.add_argument("password", type=str, help="Forgejo user's password")
group.add_argument("email", type=str, help="Gitea user's email") group.add_argument("email", type=str, help="Forgejo user's email")
group.add_argument("host", type=str, help="URI at which Gitea is running") group.add_argument("host", type=str, help="URI at which Forgejo is running")
def install(self): def install(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.install() forgejo.install()
self.install_parser = self.subparser.add_parser( self.install_parser = self.subparser.add_parser(
name="install", description="Install Gitea", help="Install Gitea" name="install", description="Install Forgejo", help="Install Forgejo"
) )
self.__add_credentials_parser(self.install_parser) self.__add_credentials_parser(self.install_parser)
self.install_parser.set_defaults(func=run) self.install_parser.set_defaults(func=run)
def register(self): def register(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.register() forgejo.register()
self.register_parser = self.subparser.add_parser( self.register_parser = self.subparser.add_parser(
name="register", name="register",
description="Gitea user registration", description="Forgejo user registration",
help="Register a user on Gitea", help="Register a user on Forgejo",
) )
self.__add_credentials_parser(self.register_parser) self.__add_credentials_parser(self.register_parser)
self.register_parser.set_defaults(func=run) self.register_parser.set_defaults(func=run)
def login(self): def login(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.login() forgejo.login()
self.login_parser = self.subparser.add_parser( self.login_parser = self.subparser.add_parser(
name="login", description="Gitea user login", help="Login on Gitea" name="login", description="Forgejo user login", help="Login on Forgejo"
) )
self.__add_credentials_parser(self.login_parser) self.__add_credentials_parser(self.login_parser)
self.login_parser.set_defaults(func=run) self.login_parser.set_defaults(func=run)
def create_repository(self): def create_repository(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.login() forgejo.login()
gitea.create_repository(name=args.repo_name) forgejo.create_repository(name=args.repo_name)
self.create_repository_parser = self.subparser.add_parser( self.create_repository_parser = self.subparser.add_parser(
name="create_repo", name="create_repo",
description="Create repository on Gitea", description="Create repository on Forgejo",
help="Create repository on Gitea", help="Create repository on Forgejo",
) )
self.__add_credentials_parser(self.create_repository_parser) self.__add_credentials_parser(self.create_repository_parser)
self.create_repository_parser.set_defaults(func=run) self.create_repository_parser.set_defaults(func=run)
@ -88,10 +88,10 @@ class Gitea:
def install_sso(self): def install_sso(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.login() forgejo.login()
print(f"CLIENT ID: {args.client_id}") print(f"CLIENT ID: {args.client_id}")
gitea.install_sso( forgejo.install_sso(
sso_name=args.sso_name, sso_name=args.sso_name,
client_id=args.client_id, client_id=args.client_id,
client_secret=args.client_secret, client_secret=args.client_secret,
@ -100,8 +100,8 @@ class Gitea:
self.install_sso_parser = self.subparser.add_parser( self.install_sso_parser = self.subparser.add_parser(
name="install_sso", name="install_sso",
description="Install SSO on Gitea", description="Install SSO on Forgejo",
help="Install SSO on Gitea", help="Install SSO on Forgejo",
) )
self.__add_credentials_parser(self.install_sso_parser) self.__add_credentials_parser(self.install_sso_parser)
self.install_sso_parser.add_argument( self.install_sso_parser.add_argument(
@ -123,14 +123,14 @@ class Gitea:
def add_deploy_key(self): def add_deploy_key(self):
def run(args, c: Session): def run(args, c: Session):
gitea = gitea_from_args(args, c=c) forgejo = forgejo_from_args(args, c=c)
gitea.login() forgejo.login()
gitea.add_deploy_key(repo=args.repo_name, key=args.key_file) forgejo.add_deploy_key(repo=args.repo_name, key=args.key_file)
self.add_deploy_key_parser = self.subparser.add_parser( self.add_deploy_key_parser = self.subparser.add_parser(
name="add_deploy_key", name="add_deploy_key",
description="Create repository on Gitea", description="Create repository on Forgejo",
help="Add deploy key to a repository on Gitea", help="Add deploy key to a repository on Forgejo",
) )
self.__add_credentials_parser(self.add_deploy_key_parser) self.__add_credentials_parser(self.add_deploy_key_parser)
self.add_deploy_key_parser.add_argument( self.add_deploy_key_parser.add_argument(
@ -203,21 +203,21 @@ class Hostea:
def support(self): def support(self):
def run(args, c: Session): def run(args, c: Session):
from .gitea import GiteaSSO from .forgejo import ForgejoSSO
dash = dash_from_args(args, c=c) dash = dash_from_args(args, c=c)
dash.login() dash.login()
gitea = GiteaSSO( forgejo = ForgejoSSO(
username=dash.username, username=dash.username,
email=dash.email, email=dash.email,
gitea_host=args.gitea_host, forgejo_host=args.forgejo_host,
hostea_org=args.gitea_hostea_org, hostea_org=args.forgejo_hostea_org,
support_repo=args.support_repo, support_repo=args.support_repo,
c=c, c=c,
) )
dash.new_ticket(gitea.new_issues_uri) dash.new_ticket(forgejo.new_issues_uri)
gitea.new_issue() forgejo.new_issue()
self.support_parser = self.subparser.add_parser( self.support_parser = self.subparser.add_parser(
name="support", name="support",
@ -226,12 +226,12 @@ class Hostea:
) )
self.__add_credentials_parser(self.support_parser) self.__add_credentials_parser(self.support_parser)
self.support_parser.add_argument( self.support_parser.add_argument(
"gitea_host", type=str, help="URI at which Gitea is running" "forgejo_host", type=str, help="URI at which Forgejo is running"
) )
self.support_parser.add_argument( self.support_parser.add_argument(
"gitea_hostea_org", "forgejo_hostea_org",
type=str, type=str,
help="Hostea namespace(username/org) on Gitea, where support repository is hosted", help="Hostea namespace(username/org) on Forgejo, where support repository is hosted",
) )
self.support_parser.add_argument( self.support_parser.add_argument(
"support_repo", type=str, help="support repository name" "support_repo", type=str, help="support repository name"
@ -245,28 +245,28 @@ class Cli:
c = Session() c = Session()
self.c = c self.c = c
self.parser = argparse.ArgumentParser( self.parser = argparse.ArgumentParser(
description="Install and Bootstrap Gitea and Hostea Dashboard" description="Install and Bootstrap Forgejo and Hostea Dashboard"
) )
self.subparser = self.parser.add_subparsers() self.subparser = self.parser.add_subparsers()
self.check_env() self.check_env()
self.gitea() self.forgejo()
self.hostea() self.hostea()
def __add_credentials_parser(self, parser): def __add_credentials_parser(self, parser):
group = parser.add_argument_group("credentials", "User credentials") group = parser.add_argument_group("credentials", "User credentials")
group.add_argument("username", type=str, help="Gitea user's username") group.add_argument("username", type=str, help="Forgejo user's username")
group.add_argument("password", type=str, help="Gitea user's password") group.add_argument("password", type=str, help="Forgejo user's password")
group.add_argument("email", type=str, help="Gitea user's email") group.add_argument("email", type=str, help="Forgejo user's email")
def check_env(self): def check_env(self):
def run(args, c: Session): def run(args, c: Session):
from .gitea import Gitea from .forgejo import Forgejo
from .hostea import Hostea from .hostea import Hostea
Hostea.check_online( Hostea.check_online(
dashboard_host=args.hostea_host, maildev_host=args.maildev_host dashboard_host=args.hostea_host, maildev_host=args.maildev_host
) )
Gitea.check_online(host=args.gitea_host) Forgejo.check_online(host=args.forgejo_host)
self.check_env_parser = self.subparser.add_parser( self.check_env_parser = self.subparser.add_parser(
name="check_env", name="check_env",
@ -275,7 +275,7 @@ class Cli:
) )
self.check_env_parser.add_argument( self.check_env_parser.add_argument(
"gitea_host", type=str, help="URI at which Gitea is running" "forgejo_host", type=str, help="URI at which Forgejo is running"
) )
self.check_env_parser.add_argument( self.check_env_parser.add_argument(
@ -295,13 +295,13 @@ class Cli:
) )
Hostea(parser=self.hostea, c=self.c) Hostea(parser=self.hostea, c=self.c)
def gitea(self): def forgejo(self):
self.gitea = self.subparser.add_parser( self.forgejo = self.subparser.add_parser(
name="gitea", name="forgejo",
description="Gitea", description="Forgejo",
help="Gitea-related functionality", help="Forgejo-related functionality",
) )
Gitea(parser=self.gitea, c=self.c) Forgejo(parser=self.forgejo, c=self.c)
def parse(self): def parse(self):
return self.parser.parse_args() return self.parser.parse_args()

View File

@ -13,7 +13,7 @@ class ParseCSRF(HTMLParser):
# return cls(name="csrfmiddlewaretoken") # return cls(name="csrfmiddlewaretoken")
# #
# @classmethod # @classmethod
# def gitea_parser(cls) -> "ParseCSRF": # def forgejo_parser(cls) -> "ParseCSRF":
# return cls(name="_csrf") # return cls(name="_csrf")
# #
def handle_starttag(self, tag: str, attrs: (str, str)): def handle_starttag(self, tag: str, attrs: (str, str)):

View File

@ -10,15 +10,15 @@ import requests
from .csrf import ParseCSRF from .csrf import ParseCSRF
# GITEA_USER = "root" # FORGEJO_USER = "root"
# GITEA_EMAIL = "root@example.com" # FORGEJO_EMAIL = "root@example.com"
# GITEA_PASSWORD = "foobarpassword" # FORGEJO_PASSWORD = "foobarpassword"
# HOST = "http://localhost:8080" # HOST = "http://localhost:8080"
# #
# REPOS = [] # REPOS = []
class Gitea: class Forgejo:
def __init__(self, host: str, username: str, password: str, email: str, c: Session): def __init__(self, host: str, username: str, password: str, email: str, c: Session):
self.host = host self.host = host
self.username = username self.username = username
@ -48,7 +48,7 @@ class Gitea:
@staticmethod @staticmethod
def check_online(host: str): def check_online(host: str):
""" """
Check if Gitea instance is online Check if Forgejo instance is online
""" """
count = 0 count = 0
parsed = urlparse(host) parsed = urlparse(host)
@ -67,7 +67,7 @@ class Gitea:
def install(self): def install(self):
""" """
Install Gitea, first form that a user sees when a new instance is Install Forgejo, first form that a user sees when a new instance is
deployed deployed
""" """
# cwd = os.environ.get("PWD") # cwd = os.environ.get("PWD")
@ -77,12 +77,12 @@ class Gitea:
"db_host": "localhost:3306", "db_host": "localhost:3306",
"db_user": "root", "db_user": "root",
"db_passwd": "", "db_passwd": "",
"db_name": "gitea", "db_name": "forgejo",
"ssl_mode": "disable", "ssl_mode": "disable",
"db_schema": "", "db_schema": "",
"charset": "utf8", "charset": "utf8",
"db_path": "/data/gitea/gitea.db", "db_path": "/data/gitea/gitea.db",
"app_name": "Gitea:+Git+with+a+cup+of+tea", "app_name": "Forgejo:+Beyond+Coding+We+Forge",
"repo_root_path": "/data/git/repositories", "repo_root_path": "/data/git/repositories",
"lfs_root_path": "/data/git/lfs", "lfs_root_path": "/data/git/lfs",
"run_user": "git", "run_user": "git",
@ -316,26 +316,26 @@ class ParseSSOLogin(HTMLParser):
return return
class GiteaSSO: class ForgejoSSO:
def __init__( def __init__(
self, self,
username: str, username: str,
email: str, email: str,
gitea_host: str, forgejo_host: str,
hostea_org: str, hostea_org: str,
support_repo: str, support_repo: str,
c: Session, c: Session,
): ):
self.c = c self.c = c
self.username = username self.username = username
self.gitea_host = gitea_host self.forgejo_host = forgejo_host
self.hostea_org = hostea_org self.hostea_org = hostea_org
self.support_repo = support_repo self.support_repo = support_repo
self.email = email self.email = email
self.__csrf_key = "_csrf" self.__csrf_key = "_csrf"
url = urlparse(self.gitea_host) url = urlparse(self.forgejo_host)
repo = f"{self.hostea_org}/{self.support_repo}" repo = f"{self.hostea_org}/{self.support_repo}"
issues = f"{repo}/issues" issues = f"{repo}/issues"
new_issues = f"{issues}/new" new_issues = f"{issues}/new"
@ -371,8 +371,8 @@ class GiteaSSO:
parser = ParseSSOLogin() parser = ParseSSOLogin()
parser.feed(resp.text) parser.feed(resp.text)
url = urlparse(self.gitea_host) url = urlparse(self.forgejo_host)
## SSO URL in Gitea login page ## SSO URL in Forgejo login page
sso = urlunparse((url.scheme, url.netloc, parser.url, "", "", "")) sso = urlunparse((url.scheme, url.netloc, parser.url, "", "", ""))
# redirects are enabled to for a cleaner implementation. Commented out # redirects are enabled to for a cleaner implementation. Commented out

View File

@ -11,12 +11,12 @@ is_ci(){
if is_ci if is_ci
then then
MAILDEV_URL="http://smtp:1080" MAILDEV_URL="http://smtp:1080"
GITEA_URL="http://gitea:3000" FORGEJO_URL="http://forgejo:3000"
GITEA_SSH_URL="ssh://git@gitea:22" FORGEJO_SSH_URL="ssh://git@forgejo:22"
else else
MAILDEV_URL="http://localhost:1080" MAILDEV_URL="http://localhost:1080"
GITEA_URL="http://localhost:3000" FORGEJO_URL="http://localhost:3000"
GITEA_SSH_URL="ssh://git@localhost:22" FORGEJO_SSH_URL="ssh://git@localhost:22"
fi fi
readonly DASHBOARD_URL="http://localhost:8000" readonly DASHBOARD_URL="http://localhost:8000"
@ -27,22 +27,22 @@ readonly DASHBOARD_OIDC_DISCOVERY_URL="$DASHBOARD_URL/o/.well-known/openid-confi
readonly DASHBOARD_ADMIN_USERNAME=root readonly DASHBOARD_ADMIN_USERNAME=root
readonly DASHBOARD_ADMIN_PASSWORD=supercomplicatedpassword readonly DASHBOARD_ADMIN_PASSWORD=supercomplicatedpassword
readonly DASHBOARD_ADMIN_EMAIL="$DASHBOARD_ADMIN_USERNAME@dash.example.org" readonly DASHBOARD_ADMIN_EMAIL="$DASHBOARD_ADMIN_USERNAME@dash.example.org"
readonly DASHBOARD_OIDC_APP_NAME=hostea-gitea readonly DASHBOARD_OIDC_APP_NAME=hostea-forgejo
readonly GITEA_ROOT_USERNAME=root readonly FORGEJO_ROOT_USERNAME=root
readonly GITEA_ROOT_EMAIL="$GITEA_ROOT_USERNAME@example.org" readonly FORGEJO_ROOT_EMAIL="$FORGEJO_ROOT_USERNAME@example.org"
readonly GITEA_ROOT_PASSOWRD=supercomplicatedpassword readonly FORGEJO_ROOT_PASSOWRD=supercomplicatedpassword
readonly GITEA_HOSTEA_SSO_NAME=hostea-sso readonly FORGEJO_HOSTEA_SSO_NAME=hostea-sso
readonly GITEA_OIDC_CALLBACK="$GITEA_URL/user/oauth2/$GITEA_HOSTEA_SSO_NAME/callback" readonly FORGEJO_OIDC_CALLBACK="$FORGEJO_URL/user/oauth2/$FORGEJO_HOSTEA_SSO_NAME/callback"
readonly GITEA_HOSTEA_FLEET_DEPLOY_KEY="$(realpath tests/fleet-deploy-key.pub)" readonly FORGEJO_HOSTEA_FLEET_DEPLOY_KEY="$(realpath tests/fleet-deploy-key.pub)"
readonly GITEA_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE="$(realpath tests/fleet-deploy-key)" readonly FORGEJO_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE="$(realpath tests/fleet-deploy-key)"
readonly GITEA_HOSTEA_USERNAME=hostea readonly FORGEJO_HOSTEA_USERNAME=hostea
readonly GITEA_HOSTEA_PASSWORD=supercomplicatedpassword readonly FORGEJO_HOSTEA_PASSWORD=supercomplicatedpassword
readonly GITEA_HOSTEA_EMAIL="$GITEA_HOSTEA_USERNAME@example.org" readonly FORGEJO_HOSTEA_EMAIL="$FORGEJO_HOSTEA_USERNAME@example.org"
readonly GITEA_HOSTEA_SUPPORT_REPO="support" readonly FORGEJO_HOSTEA_SUPPORT_REPO="support"
readonly GITEA_HOSTEA_FLEET_REPO="fleet" readonly FORGEJO_HOSTEA_FLEET_REPO="fleet"
readonly GITEA_HOSTEA_FLEET_REPO_REMOTE="$GITEA_SSH_URL/$GITEA_HOSTEA_USERNAME/$GITEA_HOSTEA_FLEET_REPO.git" readonly FORGEJO_HOSTEA_FLEET_REPO_REMOTE="$FORGEJO_SSH_URL/$FORGEJO_HOSTEA_USERNAME/$FORGEJO_HOSTEA_FLEET_REPO.git"
readonly HOSTEA_CUSTOMER_USERNAME=batman readonly HOSTEA_CUSTOMER_USERNAME=batman
readonly HOSTEA_CUSTOMER_PASSWORD=supercomplicatedpassword readonly HOSTEA_CUSTOMER_PASSWORD=supercomplicatedpassword
@ -53,7 +53,7 @@ OIDC_CLIENT_SECRET=""
wait_for_env() { wait_for_env() {
python -m integration \ python -m integration \
check_env $GITEA_URL $DASHBOARD_URL $MAILDEV_URL check_env $FORGEJO_URL $DASHBOARD_URL $MAILDEV_URL
} }
# create OIDC app on Hostea Dashboard # create OIDC app on Hostea Dashboard
@ -67,74 +67,74 @@ oidc_dashboard_init() {
resp=$(python manage.py create_oidc \ resp=$(python manage.py create_oidc \
$DASHBOARD_OIDC_APP_NAME $DASHBOARD_ADMIN_USERNAME \ $DASHBOARD_OIDC_APP_NAME $DASHBOARD_ADMIN_USERNAME \
$GITEA_OIDC_CALLBACK) $FORGEJO_OIDC_CALLBACK)
OIDC_CLIENT_ID=$(echo $resp | cut -d ":" -f 2 | cut -d " " -f 2) OIDC_CLIENT_ID=$(echo $resp | cut -d ":" -f 2 | cut -d " " -f 2)
OIDC_CLIENT_SECRET=$(echo $resp | cut -d ":" -f 3 | cut -d " " -f 2) OIDC_CLIENT_SECRET=$(echo $resp | cut -d ":" -f 3 | cut -d " " -f 2)
} }
# register root user on Gitea to simulate Hoste admin and integrate SSO # register root user on Forgejo to simulate Hoste admin and integrate SSO
gitea_root(){ forgejo_root(){
python -m integration \ python -m integration \
gitea install \ forgejo install \
$GITEA_ROOT_USERNAME $GITEA_ROOT_PASSOWRD \ $FORGEJO_ROOT_USERNAME $FORGEJO_ROOT_PASSOWRD \
$GITEA_ROOT_EMAIL \ $FORGEJO_ROOT_EMAIL \
$GITEA_URL $FORGEJO_URL
python -m integration \ python -m integration \
gitea register \ forgejo register \
$GITEA_ROOT_USERNAME $GITEA_ROOT_PASSOWRD \ $FORGEJO_ROOT_USERNAME $FORGEJO_ROOT_PASSOWRD \
$GITEA_ROOT_EMAIL \ $FORGEJO_ROOT_EMAIL \
$GITEA_URL $FORGEJO_URL
python -m integration \ python -m integration \
gitea login \ forgejo login \
$GITEA_ROOT_USERNAME $GITEA_ROOT_PASSOWRD \ $FORGEJO_ROOT_USERNAME $FORGEJO_ROOT_PASSOWRD \
$GITEA_ROOT_EMAIL \ $FORGEJO_ROOT_EMAIL \
$GITEA_URL $FORGEJO_URL
# python -m integration \ # python -m integration \
# gitea install_sso \ # forgejo install_sso \
# $GITEA_ROOT_USERNAME $GITEA_ROOT_PASSOWRD \ # $FORGEJO_ROOT_USERNAME $FORGEJO_ROOT_PASSOWRD \
# $GITEA_ROOT_EMAIL \ # $FORGEJO_ROOT_EMAIL \
# $GITEA_URL \ # $FORGEJO_URL \
# $GITEA_HOSTEA_SSO_NAME \ # $FORGEJO_HOSTEA_SSO_NAME \
# $OIDC_CLIENT_ID $OIDC_CLIENT_SECRET \ # $OIDC_CLIENT_ID $OIDC_CLIENT_SECRET \
# $DASHBOARD_OIDC_DISCOVERY_URL # $DASHBOARD_OIDC_DISCOVERY_URL
} }
# register user "Hostea" on Gitea and create support repository # register user "Hostea" on Forgejo and create support repository
support_repo_init() { support_repo_init() {
python -m integration \ python -m integration \
gitea register \ forgejo register \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL $FORGEJO_URL
python -m integration \ python -m integration \
gitea login \ forgejo login \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL $FORGEJO_URL
python -m integration \ python -m integration \
gitea create_repo \ forgejo create_repo \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL \ $FORGEJO_URL \
$GITEA_HOSTEA_SUPPORT_REPO $FORGEJO_HOSTEA_SUPPORT_REPO
} }
new_fleet_repo_init() { new_fleet_repo_init() {
python -m integration \ python -m integration \
gitea create_repo \ forgejo create_repo \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL \ $FORGEJO_URL \
$1 $1
python -m integration \ python -m integration \
gitea add_deploy_key \ forgejo add_deploy_key \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL \ $FORGEJO_URL \
$1 \ $1 \
$GITEA_HOSTEA_FLEET_DEPLOY_KEY $FORGEJO_HOSTEA_FLEET_DEPLOY_KEY
tmp_dir=$(mktemp -d) tmp_dir=$(mktemp -d)
pushd $tmp_dir pushd $tmp_dir
@ -144,13 +144,13 @@ new_fleet_repo_init() {
then then
git config user.email "hostea-dashobard-test@example.org" git config user.email "hostea-dashobard-test@example.org"
git config user.name "hoste-dashobard-test" git config user.name "hoste-dashobard-test"
chmod 600 $GITEA_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE chmod 600 $FORGEJO_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE
fi fi
git add README git add README
git commit -m "init" git commit -m "init"
REMOTE="$GITEA_SSH_URL/$GITEA_HOSTEA_USERNAME/$1.git" REMOTE="$FORGEJO_SSH_URL/$FORGEJO_HOSTEA_USERNAME/$1.git"
git remote add origin $REMOTE git remote add origin $REMOTE
GIT_SSH_COMMAND="/usr/bin/ssh -oStrictHostKeyChecking=no -i $GITEA_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE" \ GIT_SSH_COMMAND="/usr/bin/ssh -oStrictHostKeyChecking=no -i $FORGEJO_HOSTEA_FLEET_DEPLOY_KEY_PRIVATE" \
git push --set-upstream origin master git push --set-upstream origin master
popd popd
rm -rf $tmp_dir rm -rf $tmp_dir
@ -158,20 +158,20 @@ new_fleet_repo_init() {
} }
# register user "Hostea" on Gitea and create support repository # register user "Hostea" on Forgejo and create support repository
fleet_repo_init() { fleet_repo_init() {
python -m integration \ python -m integration \
gitea register \ forgejo register \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL || true $FORGEJO_URL || true
python -m integration \ python -m integration \
gitea login \ forgejo login \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_PASSWORD \ $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_PASSWORD \
$GITEA_HOSTEA_EMAIL \ $FORGEJO_HOSTEA_EMAIL \
$GITEA_URL $FORGEJO_URL
new_fleet_repo_init $GITEA_HOSTEA_FLEET_REPO new_fleet_repo_init $FORGEJO_HOSTEA_FLEET_REPO
} }
@ -192,8 +192,8 @@ hostea_customer_simulation() {
$HOSTEA_CUSTOMER_USERNAME $HOSTEA_CUSTOMER_PASSWORD \ $HOSTEA_CUSTOMER_USERNAME $HOSTEA_CUSTOMER_PASSWORD \
$HOSTEA_CUSTOMER_EMAIL \ $HOSTEA_CUSTOMER_EMAIL \
$DASHBOARD_URL \ $DASHBOARD_URL \
$GITEA_URL \ $FORGEJO_URL \
$GITEA_HOSTEA_USERNAME $GITEA_HOSTEA_SUPPORT_REPO $FORGEJO_HOSTEA_USERNAME $FORGEJO_HOSTEA_SUPPORT_REPO
} }
setup_env() { setup_env() {

View File

@ -15,7 +15,7 @@ django-oauth-toolkit==2.0.0
django-payments==1.0.0 django-payments==1.0.0
django-phonenumber-field==6.3.0 django-phonenumber-field==6.3.0
djangorestframework==3.13.1 djangorestframework==3.13.1
greenlet==1.1.2 greenlet==1.1.3.post0
idna==3.3 idna==3.3
install==1.3.5 install==1.3.5
isort==5.10.1 isort==5.10.1

View File

@ -2,7 +2,7 @@
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
<p> <p>
You will be redirected to Hostea's issue tracker You will be redirected to Gna!'s issue tracker
<span id="timer">momentarily</span>. If not, please click <span id="timer">momentarily</span>. If not, please click
<a id="redirect-url" href="{{ support.list }}">here.</a> <a id="redirect-url" href="{{ support.list }}">here.</a>
</p> </p>

View File

@ -2,7 +2,7 @@
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
<p> <p>
You will be redirected to Hostea's issue tracker You will be redirected to Gna!'s issue tracker
<span id="timer">momentarily</span>. If not, please click <span id="timer">momentarily</span>. If not, please click
<a id="redirect-url" href="{{ support.new }}">here.</a> <a id="redirect-url" href="{{ support.new }}">here.</a>
</p> </p>

View File

@ -24,8 +24,8 @@ from .utils import IssueTracker
hostea_issue_tracker_settings = settings.HOSTEA hostea_issue_tracker_settings = settings.HOSTEA
hostea_issue_tracker_settings["META"] = { hostea_issue_tracker_settings["META"] = {
"GITEA_INSTANCE": "https://gitea.hostea.org", "FORGEJO_INSTANCE": "https://forgejo.gna.org",
"GITEA_ORG_NAME": "Hostea", "FORGEJO_ORG_NAME": "Hostea",
"SUPPORT_REPOSITORY": "support", "SUPPORT_REPOSITORY": "support",
} }
@ -41,8 +41,8 @@ class IssueTrackerTests(TestCase):
Verify default credentials; all further tests are based on defaults set Verify default credentials; all further tests are based on defaults set
""" """
it = IssueTracker() it = IssueTracker()
self.assertEqual(it.config["GITEA_INSTANCE"], "https://gitea.hostea.org") self.assertEqual(it.config["FORGEJO_INSTANCE"], "https://forgejo.gna.org")
self.assertEqual(it.config["GITEA_ORG_NAME"], "Hostea") self.assertEqual(it.config["FORGEJO_ORG_NAME"], "Hostea")
self.assertEqual(it.config["SUPPORT_REPOSITORY"], "support") self.assertEqual(it.config["SUPPORT_REPOSITORY"], "support")
def test_uri_builders(self): def test_uri_builders(self):
@ -51,10 +51,10 @@ class IssueTrackerTests(TestCase):
""" """
it = IssueTracker() it = IssueTracker()
self.assertEqual( self.assertEqual(
it.get_issue_tracker(), "https://gitea.hostea.org/Hostea/support/issues" it.get_issue_tracker(), "https://forgejo.gna.org/Hostea/support/issues"
) )
self.assertEqual( self.assertEqual(
it.open_issue(), "https://gitea.hostea.org/Hostea/support/issues/new" it.open_issue(), "https://forgejo.gna.org/Hostea/support/issues/new"
) )

View File

@ -24,9 +24,9 @@ class IssueTracker:
def __init__(self): def __init__(self):
self.config = settings.HOSTEA["META"] self.config = settings.HOSTEA["META"]
self.instance = urlparse(self.config["GITEA_INSTANCE"]) self.instance = urlparse(self.config["FORGEJO_INSTANCE"])
self.repo = ( self.repo = (
f"{self.config['GITEA_ORG_NAME']}/{self.config['SUPPORT_REPOSITORY']}" f"{self.config['FORGEJO_ORG_NAME']}/{self.config['SUPPORT_REPOSITORY']}"
) )
self.issues = f"{self.repo}/issues" self.issues = f"{self.repo}/issues"