[WEB-5262] feat: gitea sso (#8022)
* Feature/7137/gitea sso (#7940) * added gitea auth to admin panel with configs , added api calls * added gitea to oauth root (for signup and signin) * removed log * replace github oauth with gitea ouath error messages * added gitea to auth root * fix: update token expiration handling and remove unused variable in Gitea callback * fix: include Gitea in OAuth enabled checks * fix: improve error handling when fetching emails from Gitea * chore : remove logs and add semicolons * refactor: update Gitea authentication components and imports for consistency * fix: enhance Gitea authentication form to auto-populate host value and improve OAuth checks * refactor: enhance Gitea OAuth provider with improved error handling and URL validation * fix: update authentication success messages to check for string value "1" --------- Co-authored-by: Shivam Jain <shivam.clgstash@gmail.com> Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
This commit is contained in:
parent
69fe581fd8
commit
1126ca30b0
23 changed files with 897 additions and 7 deletions
|
|
@ -38,9 +38,11 @@ AUTHENTICATION_ERROR_CODES = {
|
|||
"GITHUB_NOT_CONFIGURED": 5110,
|
||||
"GITHUB_USER_NOT_IN_ORG": 5122,
|
||||
"GITLAB_NOT_CONFIGURED": 5111,
|
||||
"GITEA_NOT_CONFIGURED": 5112,
|
||||
"GOOGLE_OAUTH_PROVIDER_ERROR": 5115,
|
||||
"GITHUB_OAUTH_PROVIDER_ERROR": 5120,
|
||||
"GITLAB_OAUTH_PROVIDER_ERROR": 5121,
|
||||
"GITEA_OAUTH_PROVIDER_ERROR": 5123,
|
||||
# Reset Password
|
||||
"INVALID_PASSWORD_TOKEN": 5125,
|
||||
"EXPIRED_PASSWORD_TOKEN": 5130,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class OauthAdapter(Adapter):
|
|||
return "GITHUB_OAUTH_PROVIDER_ERROR"
|
||||
elif self.provider == "gitlab":
|
||||
return "GITLAB_OAUTH_PROVIDER_ERROR"
|
||||
elif self.provider == "gitea":
|
||||
return "GITEA_OAUTH_PROVIDER_ERROR"
|
||||
else:
|
||||
return "OAUTH_NOT_CONFIGURED"
|
||||
|
||||
|
|
|
|||
171
apps/api/plane/authentication/provider/oauth/gitea.py
Normal file
171
apps/api/plane/authentication/provider/oauth/gitea.py
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from urllib.parse import urlencode, urlparse
|
||||
import pytz
|
||||
import requests
|
||||
|
||||
# Module imports
|
||||
from plane.authentication.adapter.oauth import OauthAdapter
|
||||
from plane.license.utils.instance_value import get_configuration_value
|
||||
from plane.authentication.adapter.error import (
|
||||
AUTHENTICATION_ERROR_CODES,
|
||||
AuthenticationException,
|
||||
)
|
||||
|
||||
|
||||
class GiteaOAuthProvider(OauthAdapter):
|
||||
provider = "gitea"
|
||||
scope = "openid email profile"
|
||||
|
||||
def __init__(self, request, code=None, state=None, callback=None):
|
||||
(GITEA_CLIENT_ID, GITEA_CLIENT_SECRET, GITEA_HOST) = get_configuration_value(
|
||||
[
|
||||
{
|
||||
"key": "GITEA_CLIENT_ID",
|
||||
"default": os.environ.get("GITEA_CLIENT_ID"),
|
||||
},
|
||||
{
|
||||
"key": "GITEA_CLIENT_SECRET",
|
||||
"default": os.environ.get("GITEA_CLIENT_SECRET"),
|
||||
},
|
||||
{
|
||||
"key": "GITEA_HOST",
|
||||
"default": os.environ.get("GITEA_HOST"),
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
if not (GITEA_CLIENT_ID and GITEA_CLIENT_SECRET and GITEA_HOST):
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_NOT_CONFIGURED"],
|
||||
error_message="GITEA_NOT_CONFIGURED",
|
||||
)
|
||||
|
||||
# Enforce scheme and normalize trailing slash(es)
|
||||
parsed = urlparse(GITEA_HOST)
|
||||
if not parsed.scheme or parsed.scheme not in ("https", "http"):
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_NOT_CONFIGURED"],
|
||||
error_message="GITEA_NOT_CONFIGURED", # avoid leaking details to query params
|
||||
)
|
||||
GITEA_HOST = GITEA_HOST.rstrip("/")
|
||||
|
||||
# Set URLs based on the host
|
||||
self.token_url = f"{GITEA_HOST}/login/oauth/access_token"
|
||||
self.userinfo_url = f"{GITEA_HOST}/api/v1/user"
|
||||
|
||||
client_id = GITEA_CLIENT_ID
|
||||
client_secret = GITEA_CLIENT_SECRET
|
||||
|
||||
redirect_uri = f"{'https' if request.is_secure() else 'http'}://{request.get_host()}/auth/gitea/callback/"
|
||||
url_params = {
|
||||
"client_id": client_id,
|
||||
"scope": self.scope,
|
||||
"redirect_uri": redirect_uri,
|
||||
"response_type": "code",
|
||||
"state": state,
|
||||
}
|
||||
auth_url = f"{GITEA_HOST}/login/oauth/authorize?{urlencode(url_params)}"
|
||||
|
||||
super().__init__(
|
||||
request,
|
||||
self.provider,
|
||||
client_id,
|
||||
self.scope,
|
||||
redirect_uri,
|
||||
auth_url,
|
||||
self.token_url,
|
||||
self.userinfo_url,
|
||||
client_secret,
|
||||
code,
|
||||
callback=callback,
|
||||
)
|
||||
|
||||
def set_token_data(self):
|
||||
data = {
|
||||
"code": self.code,
|
||||
"client_id": self.client_id,
|
||||
"client_secret": self.client_secret,
|
||||
"redirect_uri": self.redirect_uri,
|
||||
"grant_type": "authorization_code",
|
||||
}
|
||||
headers = {"Accept": "application/json"}
|
||||
token_response = self.get_user_token(data=data, headers=headers)
|
||||
super().set_token_data(
|
||||
{
|
||||
"access_token": token_response.get("access_token"),
|
||||
"refresh_token": token_response.get("refresh_token", None),
|
||||
"access_token_expired_at": (
|
||||
datetime.now(tz=pytz.utc) + timedelta(seconds=token_response.get("expires_in"))
|
||||
if token_response.get("expires_in")
|
||||
else None
|
||||
),
|
||||
"refresh_token_expired_at": (
|
||||
datetime.fromtimestamp(
|
||||
token_response.get("refresh_token_expired_at"), tz=pytz.utc
|
||||
)
|
||||
if token_response.get("refresh_token_expired_at")
|
||||
else None
|
||||
),
|
||||
"id_token": token_response.get("id_token", ""),
|
||||
}
|
||||
)
|
||||
|
||||
def __get_email(self, headers):
|
||||
try:
|
||||
# Gitea may not provide email in user response, so fetch it separately
|
||||
emails_url = f"{self.userinfo_url}/emails"
|
||||
response = requests.get(emails_url, headers=headers)
|
||||
if not response.ok:
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR: Failed to fetch emails",
|
||||
)
|
||||
emails_response = response.json()
|
||||
|
||||
if not emails_response:
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR: No emails found",
|
||||
)
|
||||
# Prefer primary+verified, then any verified, then primary, else first
|
||||
email = next((e.get("email") for e in emails_response if e.get("primary") and e.get("verified")), None)
|
||||
if not email:
|
||||
email = next((e.get("email") for e in emails_response if e.get("verified")), None)
|
||||
if not email:
|
||||
email = next((e.get("email") for e in emails_response if e.get("primary")), None)
|
||||
if not email and emails_response:
|
||||
# If no primary email, use the first one
|
||||
email = emails_response[0].get("email")
|
||||
return email
|
||||
except requests.RequestException:
|
||||
raise AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR: Exception occurred while fetching emails",
|
||||
)
|
||||
|
||||
def set_user_data(self):
|
||||
user_info_response = self.get_user_response()
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.token_data.get('access_token')}",
|
||||
"Accept": "application/json",
|
||||
}
|
||||
|
||||
# Get email if not provided in user info
|
||||
email = user_info_response.get("email")
|
||||
if not email:
|
||||
email = self.__get_email(headers=headers)
|
||||
|
||||
super().set_user_data(
|
||||
{
|
||||
"email": email,
|
||||
"user": {
|
||||
"provider_id": str(user_info_response.get("id")),
|
||||
"email": email,
|
||||
"avatar": user_info_response.get("avatar_url"),
|
||||
"first_name": user_info_response.get("full_name") or user_info_response.get("login"),
|
||||
"last_name": "", # Gitea doesn't provide separate first/last name
|
||||
"is_password_autoset": True,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
|
@ -36,6 +36,10 @@ from .views import (
|
|||
SignInAuthSpaceEndpoint,
|
||||
SignUpAuthSpaceEndpoint,
|
||||
SignOutAuthSpaceEndpoint,
|
||||
GiteaCallbackEndpoint,
|
||||
GiteaOauthInitiateEndpoint,
|
||||
GiteaCallbackSpaceEndpoint,
|
||||
GiteaOauthInitiateSpaceEndpoint,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
|
|
@ -129,4 +133,17 @@ urlpatterns = [
|
|||
),
|
||||
path("change-password/", ChangePasswordEndpoint.as_view(), name="forgot-password"),
|
||||
path("set-password/", SetUserPasswordEndpoint.as_view(), name="set-password"),
|
||||
## Gitea Oauth
|
||||
path("gitea/", GiteaOauthInitiateEndpoint.as_view(), name="gitea-initiate"),
|
||||
path("gitea/callback/", GiteaCallbackEndpoint.as_view(), name="gitea-callback"),
|
||||
path(
|
||||
"spaces/gitea/",
|
||||
GiteaOauthInitiateSpaceEndpoint.as_view(),
|
||||
name="space-gitea-initiate",
|
||||
),
|
||||
path(
|
||||
"spaces/gitea/callback/",
|
||||
GiteaCallbackSpaceEndpoint.as_view(),
|
||||
name="space-gitea-callback",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from .app.check import EmailCheckEndpoint
|
|||
from .app.email import SignInAuthEndpoint, SignUpAuthEndpoint
|
||||
from .app.github import GitHubCallbackEndpoint, GitHubOauthInitiateEndpoint
|
||||
from .app.gitlab import GitLabCallbackEndpoint, GitLabOauthInitiateEndpoint
|
||||
from .app.gitea import GiteaCallbackEndpoint, GiteaOauthInitiateEndpoint
|
||||
from .app.google import GoogleCallbackEndpoint, GoogleOauthInitiateEndpoint
|
||||
from .app.magic import MagicGenerateEndpoint, MagicSignInEndpoint, MagicSignUpEndpoint
|
||||
|
||||
|
|
@ -17,6 +18,8 @@ from .space.github import GitHubCallbackSpaceEndpoint, GitHubOauthInitiateSpaceE
|
|||
|
||||
from .space.gitlab import GitLabCallbackSpaceEndpoint, GitLabOauthInitiateSpaceEndpoint
|
||||
|
||||
from .space.gitea import GiteaCallbackSpaceEndpoint, GiteaOauthInitiateSpaceEndpoint
|
||||
|
||||
from .space.google import GoogleCallbackSpaceEndpoint, GoogleOauthInitiateSpaceEndpoint
|
||||
|
||||
from .space.magic import (
|
||||
|
|
|
|||
109
apps/api/plane/authentication/views/app/gitea.py
Normal file
109
apps/api/plane/authentication/views/app/gitea.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import uuid
|
||||
from urllib.parse import urlencode, urljoin
|
||||
|
||||
# Django import
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.views import View
|
||||
|
||||
# Module imports
|
||||
from plane.authentication.provider.oauth.gitea import GiteaOAuthProvider
|
||||
from plane.authentication.utils.login import user_login
|
||||
from plane.authentication.utils.redirection_path import get_redirection_path
|
||||
from plane.authentication.utils.user_auth_workflow import post_user_auth_workflow
|
||||
from plane.license.models import Instance
|
||||
from plane.authentication.utils.host import base_host
|
||||
from plane.authentication.adapter.error import (
|
||||
AuthenticationException,
|
||||
AUTHENTICATION_ERROR_CODES,
|
||||
)
|
||||
from plane.utils.path_validator import validate_next_path
|
||||
|
||||
|
||||
class GiteaOauthInitiateEndpoint(View):
|
||||
def get(self, request):
|
||||
# Get host and next path
|
||||
request.session["host"] = base_host(request=request, is_app=True)
|
||||
next_path = request.GET.get("next_path")
|
||||
if next_path:
|
||||
request.session["next_path"] = str(validate_next_path(next_path))
|
||||
|
||||
# Check instance configuration
|
||||
instance = Instance.objects.first()
|
||||
if instance is None or not instance.is_setup_done:
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
|
||||
error_message="INSTANCE_NOT_CONFIGURED",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = urljoin(
|
||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
||||
)
|
||||
return HttpResponseRedirect(url)
|
||||
try:
|
||||
state = uuid.uuid4().hex
|
||||
provider = GiteaOAuthProvider(request=request, state=state)
|
||||
request.session["state"] = state
|
||||
auth_url = provider.get_auth_url()
|
||||
return HttpResponseRedirect(auth_url)
|
||||
except AuthenticationException as e:
|
||||
params = e.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = urljoin(
|
||||
base_host(request=request, is_app=True), "?" + urlencode(params)
|
||||
)
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
class GiteaCallbackEndpoint(View):
|
||||
def get(self, request):
|
||||
code = request.GET.get("code")
|
||||
state = request.GET.get("state")
|
||||
base_host = request.session.get("host")
|
||||
next_path = request.session.get("next_path")
|
||||
|
||||
if state != request.session.get("state", ""):
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(next_path)
|
||||
url = urljoin(base_host, "?" + urlencode(params))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
if not code:
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = urljoin(base_host, "?" + urlencode(params))
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
try:
|
||||
provider = GiteaOAuthProvider(
|
||||
request=request, code=code, callback=post_user_auth_workflow
|
||||
)
|
||||
user = provider.authenticate()
|
||||
# Login the user and record his device info
|
||||
user_login(request=request, user=user, is_app=True)
|
||||
# Get the redirection path
|
||||
if next_path:
|
||||
path = str(validate_next_path(next_path))
|
||||
else:
|
||||
path = get_redirection_path(user=user)
|
||||
# redirect to referer path
|
||||
url = urljoin(base_host, path)
|
||||
return HttpResponseRedirect(url)
|
||||
except AuthenticationException as e:
|
||||
params = e.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = urljoin(base_host, "?" + urlencode(params))
|
||||
return HttpResponseRedirect(url)
|
||||
100
apps/api/plane/authentication/views/space/gitea.py
Normal file
100
apps/api/plane/authentication/views/space/gitea.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Python imports
|
||||
import uuid
|
||||
from urllib.parse import urlencode
|
||||
|
||||
# Django import
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.views import View
|
||||
|
||||
# Module imports
|
||||
from plane.authentication.provider.oauth.gitea import GiteaOAuthProvider
|
||||
from plane.authentication.utils.login import user_login
|
||||
from plane.license.models import Instance
|
||||
from plane.authentication.utils.host import base_host
|
||||
from plane.authentication.adapter.error import (
|
||||
AUTHENTICATION_ERROR_CODES,
|
||||
AuthenticationException,
|
||||
)
|
||||
from plane.utils.path_validator import validate_next_path
|
||||
|
||||
|
||||
class GiteaOauthInitiateSpaceEndpoint(View):
|
||||
def get(self, request):
|
||||
# Get host and next path
|
||||
request.session["host"] = base_host(request=request, is_space=True)
|
||||
next_path = request.GET.get("next_path")
|
||||
if next_path:
|
||||
request.session["next_path"] = str(validate_next_path(next_path))
|
||||
|
||||
# Check instance configuration
|
||||
instance = Instance.objects.first()
|
||||
if instance is None or not instance.is_setup_done:
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["INSTANCE_NOT_CONFIGURED"],
|
||||
error_message="INSTANCE_NOT_CONFIGURED",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
try:
|
||||
state = uuid.uuid4().hex
|
||||
provider = GiteaOAuthProvider(request=request, state=state)
|
||||
request.session["state"] = state
|
||||
auth_url = provider.get_auth_url()
|
||||
return HttpResponseRedirect(auth_url)
|
||||
except AuthenticationException as e:
|
||||
params = e.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(next_path)
|
||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
|
||||
class GiteaCallbackSpaceEndpoint(View):
|
||||
def get(self, request):
|
||||
code = request.GET.get("code")
|
||||
state = request.GET.get("state")
|
||||
next_path = request.session.get("next_path")
|
||||
|
||||
if state != request.session.get("state", ""):
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
if not code:
|
||||
exc = AuthenticationException(
|
||||
error_code=AUTHENTICATION_ERROR_CODES["GITEA_OAUTH_PROVIDER_ERROR"],
|
||||
error_message="GITEA_OAUTH_PROVIDER_ERROR",
|
||||
)
|
||||
params = exc.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
try:
|
||||
provider = GiteaOAuthProvider(request=request, code=code)
|
||||
user = provider.authenticate()
|
||||
# Login the user and record his device info
|
||||
user_login(request=request, user=user, is_space=True)
|
||||
# Process workspace and project invitations
|
||||
# redirect to referer path
|
||||
url = (
|
||||
f"{base_host(request=request, is_space=True)}{str(validate_next_path(next_path)) if next_path else ''}"
|
||||
)
|
||||
return HttpResponseRedirect(url)
|
||||
except AuthenticationException as e:
|
||||
params = e.get_error_dict()
|
||||
if next_path:
|
||||
params["next_path"] = str(validate_next_path(next_path))
|
||||
url = f"{base_host(request=request, is_space=True)}?{urlencode(params)}"
|
||||
return HttpResponseRedirect(url)
|
||||
|
|
@ -50,6 +50,7 @@ class InstanceEndpoint(BaseAPIView):
|
|||
IS_GITHUB_ENABLED,
|
||||
GITHUB_APP_NAME,
|
||||
IS_GITLAB_ENABLED,
|
||||
IS_GITEA_ENABLED,
|
||||
EMAIL_HOST,
|
||||
ENABLE_MAGIC_LINK_LOGIN,
|
||||
ENABLE_EMAIL_PASSWORD,
|
||||
|
|
@ -86,6 +87,10 @@ class InstanceEndpoint(BaseAPIView):
|
|||
"key": "IS_GITLAB_ENABLED",
|
||||
"default": os.environ.get("IS_GITLAB_ENABLED", "0"),
|
||||
},
|
||||
{
|
||||
"key": "IS_GITEA_ENABLED",
|
||||
"default": os.environ.get("IS_GITEA_ENABLED", "0"),
|
||||
},
|
||||
{"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST", "")},
|
||||
{
|
||||
"key": "ENABLE_MAGIC_LINK_LOGIN",
|
||||
|
|
@ -134,6 +139,7 @@ class InstanceEndpoint(BaseAPIView):
|
|||
data["is_google_enabled"] = IS_GOOGLE_ENABLED == "1"
|
||||
data["is_github_enabled"] = IS_GITHUB_ENABLED == "1"
|
||||
data["is_gitlab_enabled"] = IS_GITLAB_ENABLED == "1"
|
||||
data["is_gitea_enabled"] = IS_GITEA_ENABLED == "1"
|
||||
data["is_magic_login_enabled"] = ENABLE_MAGIC_LINK_LOGIN == "1"
|
||||
data["is_email_password_enabled"] = ENABLE_EMAIL_PASSWORD == "1"
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,30 @@ class Command(BaseCommand):
|
|||
"category": "INTERCOM",
|
||||
"is_encrypted": False,
|
||||
},
|
||||
{
|
||||
"key": "IS_GITEA_ENABLED",
|
||||
"value": os.environ.get("IS_GITEA_ENABLED", "0"),
|
||||
"category": "GITEA",
|
||||
"is_encrypted": False,
|
||||
},
|
||||
{
|
||||
"key": "GITEA_HOST",
|
||||
"value": os.environ.get("GITEA_HOST"),
|
||||
"category": "GITEA",
|
||||
"is_encrypted": False,
|
||||
},
|
||||
{
|
||||
"key": "GITEA_CLIENT_ID",
|
||||
"value": os.environ.get("GITEA_CLIENT_ID"),
|
||||
"category": "GITEA",
|
||||
"is_encrypted": False,
|
||||
},
|
||||
{
|
||||
"key": "GITEA_CLIENT_SECRET",
|
||||
"value": os.environ.get("GITEA_CLIENT_SECRET"),
|
||||
"category": "GITEA",
|
||||
"is_encrypted": True,
|
||||
},
|
||||
]
|
||||
|
||||
for item in config_keys:
|
||||
|
|
@ -203,7 +227,7 @@ class Command(BaseCommand):
|
|||
else:
|
||||
self.stdout.write(self.style.WARNING(f"{obj.key} configuration already exists"))
|
||||
|
||||
keys = ["IS_GOOGLE_ENABLED", "IS_GITHUB_ENABLED", "IS_GITLAB_ENABLED"]
|
||||
keys = ["IS_GOOGLE_ENABLED", "IS_GITHUB_ENABLED", "IS_GITLAB_ENABLED", "IS_GITEA_ENABLED"]
|
||||
if not InstanceConfiguration.objects.filter(key__in=keys).exists():
|
||||
for key in keys:
|
||||
if key == "IS_GOOGLE_ENABLED":
|
||||
|
|
@ -282,6 +306,48 @@ class Command(BaseCommand):
|
|||
is_encrypted=False,
|
||||
)
|
||||
self.stdout.write(self.style.SUCCESS(f"{key} loaded with value from environment variable."))
|
||||
if key == "IS_GITEA_ENABLED":
|
||||
GITEA_HOST, GITEA_CLIENT_ID, GITEA_CLIENT_SECRET = (
|
||||
get_configuration_value(
|
||||
[
|
||||
{
|
||||
"key": "GITEA_HOST",
|
||||
"default": os.environ.get(
|
||||
"GITEA_HOST", ""
|
||||
),
|
||||
},
|
||||
{
|
||||
"key": "GITEA_CLIENT_ID",
|
||||
"default": os.environ.get("GITEA_CLIENT_ID", ""),
|
||||
},
|
||||
{
|
||||
"key": "GITEA_CLIENT_SECRET",
|
||||
"default": os.environ.get(
|
||||
"GITEA_CLIENT_SECRET", ""
|
||||
),
|
||||
},
|
||||
]
|
||||
)
|
||||
)
|
||||
if (
|
||||
bool(GITEA_HOST)
|
||||
and bool(GITEA_CLIENT_ID)
|
||||
and bool(GITEA_CLIENT_SECRET)
|
||||
):
|
||||
value = "1"
|
||||
else:
|
||||
value = "0"
|
||||
InstanceConfiguration.objects.create(
|
||||
key="IS_GITEA_ENABLED",
|
||||
value=value,
|
||||
category="AUTHENTICATION",
|
||||
is_encrypted=False,
|
||||
)
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"{key} loaded with value from environment variable."
|
||||
)
|
||||
)
|
||||
else:
|
||||
for key in keys:
|
||||
self.stdout.write(self.style.WARNING(f"{key} configuration already exists"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue