diff --git a/mlaas/__pycache__/settings.cpython-310.pyc b/mlaas/__pycache__/settings.cpython-310.pyc index f788d33ee151854c64446ae4eca1f0ed4bd8ade1..b40f363086c9c9309b27a33e6a79f41a8a3dc175 100644 Binary files a/mlaas/__pycache__/settings.cpython-310.pyc and b/mlaas/__pycache__/settings.cpython-310.pyc differ diff --git a/mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc b/mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1366c37d9f748f5ce6c1aaf8ec1d9ecd4d7f2b0 Binary files /dev/null and b/mlaas/middleware/__pycache__/ai_engineer_auth.cpython-310.pyc differ diff --git a/mlaas/middleware/ai_engineer_auth.py b/mlaas/middleware/ai_engineer_auth.py new file mode 100644 index 0000000000000000000000000000000000000000..6921cf08f43a4a317c6f665563513eb7b5cf4619 --- /dev/null +++ b/mlaas/middleware/ai_engineer_auth.py @@ -0,0 +1,28 @@ +# ai_engineer_auth.py +from django.shortcuts import redirect +from django.urls import reverse +from django.contrib.auth.models import User +from prediction_service.models import UserProfile + +class AIEngineerAuthMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + if request.path == reverse('MLAAS-register'): + # Skip authorization check for the registration page + response = self.get_response(request) + return response + + if hasattr(request, 'user') and request.user.is_authenticated: + try: + user_profile = UserProfile.objects.get(user=request.user) + if user_profile.role == 'ai_engineer' and not user_profile.is_authorized: + # Redirect to unauthorized page or perform other actions + return redirect('MLAAS-login') + except UserProfile.DoesNotExist: + # Handle case where UserProfile does not exist + pass + + response = self.get_response(request) + return response diff --git a/mlaas/settings.py b/mlaas/settings.py index 1d8279860ecc1d263b82aa1823d9dd6f9877272f..a74d4faaeee09df263b5ec89532641e2119df922 100644 --- a/mlaas/settings.py +++ b/mlaas/settings.py @@ -45,6 +45,7 @@ MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django_session_timeout.middleware.SessionTimeoutMiddleware',# middlewear to delete current session after specified time SESSION_EXPIRE_SECONDS 'django.middleware.common.CommonMiddleware', + 'mlaas.middleware.ai_engineer_auth.AIEngineerAuthMiddleware',# custom middlewear that checks if user is authorized to view page 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', diff --git a/prediction_service/__pycache__/admin.cpython-310.pyc b/prediction_service/__pycache__/admin.cpython-310.pyc index c1504645d10a35ba7f6aa3cedaa99ecc4c2bf5dd..50aa0f37e655a4e3cbe61002b4008c38c3a1f044 100644 Binary files a/prediction_service/__pycache__/admin.cpython-310.pyc and b/prediction_service/__pycache__/admin.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/backends.cpython-310.pyc b/prediction_service/__pycache__/backends.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f347b86d68c7846d63dc5aa6f3fd08b19c2af62e Binary files /dev/null and b/prediction_service/__pycache__/backends.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/forms.cpython-310.pyc b/prediction_service/__pycache__/forms.cpython-310.pyc index 65ce3999e709adc67bd43d6741df0fb5ab8029d8..799a389ced0edd5b3172d0368cacc42516d299b5 100644 Binary files a/prediction_service/__pycache__/forms.cpython-310.pyc and b/prediction_service/__pycache__/forms.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/middleware.cpython-310.pyc b/prediction_service/__pycache__/middleware.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3a3ac86bb3d10e26b2aedf08e11f03b7a7b2656 Binary files /dev/null and b/prediction_service/__pycache__/middleware.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/models.cpython-310.pyc b/prediction_service/__pycache__/models.cpython-310.pyc index 50c27cd026bc5a13998e1b7524438bade92f2ef0..86d32afbfa6cf15951ac4193cb4f909a2bd01b05 100644 Binary files a/prediction_service/__pycache__/models.cpython-310.pyc and b/prediction_service/__pycache__/models.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/urls.cpython-310.pyc b/prediction_service/__pycache__/urls.cpython-310.pyc index 02683f73fd283f2eac80e14d202a8d1914655123..3994335e1991fecedc1724a0dad612742ac43c45 100644 Binary files a/prediction_service/__pycache__/urls.cpython-310.pyc and b/prediction_service/__pycache__/urls.cpython-310.pyc differ diff --git a/prediction_service/__pycache__/views.cpython-310.pyc b/prediction_service/__pycache__/views.cpython-310.pyc index 75ea0217cd183b744d09f743647419b2ebea4e96..3bf7b8c4c54e6585584a01ac3e09da23a139bd58 100644 Binary files a/prediction_service/__pycache__/views.cpython-310.pyc and b/prediction_service/__pycache__/views.cpython-310.pyc differ diff --git a/prediction_service/admin.py b/prediction_service/admin.py index 640d4b813599dca7adae6c92145203c6f8f0b0aa..97ce197b86f52e760324c9dc2f5a074ca5fa81a0 100644 --- a/prediction_service/admin.py +++ b/prediction_service/admin.py @@ -8,4 +8,18 @@ from .models import MLModel # Register your models here to the admin page admin.site.register(Post) admin.site.register(MLModel) -admin.site.register(UserProfile) \ No newline at end of file +admin.site.register(UserProfile) + +from .models import AIEngineer + +@admin.register(AIEngineer) +class AIEngineerAdmin(admin.ModelAdmin): + list_display = ['user', 'is_authorized'] + list_filter = ['is_authorized'] + actions = ['approve_engineer', 'reject_engineer'] + + def approve_engineer(self, request, queryset): + queryset.update(is_authorized=True) + + def reject_engineer(self, request, queryset): + queryset.update(is_authorized=False) \ No newline at end of file diff --git a/prediction_service/forms.py b/prediction_service/forms.py index 5385eef3ce0c4263debfea60b40c2cfcc2f1cfef..c8a56a55a14cf8ed9643be79070beb774df3ec68 100644 --- a/prediction_service/forms.py +++ b/prediction_service/forms.py @@ -1,11 +1,11 @@ from django import forms +from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User -from django.contrib.auth.forms import UserCreationForm #django implemented registration - -class UserRegisterForm(UserCreationForm):# inherits from usercreationform and adds email to the form - email = forms.EmailField()# create the email field +class UserRegisterForm(UserCreationForm): + email = forms.EmailField() + role = forms.ChoiceField(choices=[('user', 'User'), ('ai_engineer', 'AI Engineer')], widget=forms.RadioSelect) class Meta: model = User - fields = ['username','email', 'password1', 'password2'] #place elements and email field in order \ No newline at end of file + fields = ['username', 'email', 'password1', 'password2', 'role'] diff --git a/prediction_service/migrations/0009_aiengineer_is_authorized.py b/prediction_service/migrations/0009_aiengineer_is_authorized.py new file mode 100644 index 0000000000000000000000000000000000000000..2b0b7478dcc71e4a32987a0d9bc564e92c6ff910 --- /dev/null +++ b/prediction_service/migrations/0009_aiengineer_is_authorized.py @@ -0,0 +1,18 @@ +# Generated by Django 4.1.4 on 2024-03-29 11:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('prediction_service', '0008_post_slug'), + ] + + operations = [ + migrations.AddField( + model_name='aiengineer', + name='is_authorized', + field=models.BooleanField(default=False), + ), + ] diff --git a/prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc b/prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e847c26be1a72baa8ed5e9eba9cc5fa6cac72b88 Binary files /dev/null and b/prediction_service/migrations/__pycache__/0009_aiengineer_is_authorized.cpython-310.pyc differ diff --git a/prediction_service/models.py b/prediction_service/models.py index 22fa64aca7ba1d8f631083985409c1958e0617bd..d3f147c115c68cb063a33464a78c82b700b6d5b7 100644 --- a/prediction_service/models.py +++ b/prediction_service/models.py @@ -22,7 +22,7 @@ class EndUser(models.Model): class AIEngineer(models.Model): user = models.OneToOneField(UserProfile, on_delete=models.CASCADE) - # Add other fields as needed + is_authorized = models.BooleanField(default=False) class Administrator(models.Model): user = models.OneToOneField(UserProfile, on_delete=models.CASCADE) diff --git a/prediction_service/templates/prediction_service/login.html b/prediction_service/templates/prediction_service/login.html index 72632901dc7c7e428c5b5b1d6f97f79700bb0796..47be2091eba30a31e7c71ac7885a66889016ba63 100644 --- a/prediction_service/templates/prediction_service/login.html +++ b/prediction_service/templates/prediction_service/login.html @@ -2,28 +2,39 @@ {% block content %} - <div class="container d-flex justify-content-center"> +<div class="container d-flex justify-content-center"> + <div class="row col-sm-4"> + <h1>MLAAS Login</h1> + <form method="post"> + {% csrf_token %} + <fieldset class="form-group"> + <legend class="border-bottom mb-4">Log In</legend> + {% if error_message %} + <p class="text-danger">{{ error_message }}</p> + {% endif %} + <!-- Add fields for username and password manually --> + <div class="form-group"> + <label for="id_username">Username:</label> + <input type="text" name="username" id="id_username" class="form-control"> + </div> + <div class="form-group"> + <label for="id_password">Password:</label> + <input type="password" name="password" id="id_password" class="form-control"> + </div> + </fieldset> - <div class="row col-sm-4"> - <h1>MLAAS Login</h1> - <form method="post"> - {% csrf_token %} - <fieldset class="form-group"> - <legend class="border-bottom mb-4">Log In</legend> - {{ form.as_p }} - </fieldset> - <div class="form-group"> - <button class="btn btn-outline-info" type="submit">login</button> - </div> - </form> - - <div class="border-top pt-3"> - <small class="text-muted"> - Need have an account? <a class="ml-2" href="{% url 'MLAAS-register' %}">Sign up now</a>. - </small> + <div class="form-group"> + <button class="btn btn-outline-info" type="submit">Login</button> </div> - + </form> + + <div class="border-top pt-3"> + <small class="text-muted"> + Need to create an account? <a class="ml-2" href="{% url 'MLAAS-register' %}">Sign up now</a>. + </small> </div> + </div> +</div> -{% endblock content %} \ No newline at end of file +{% endblock content %} diff --git a/prediction_service/templates/prediction_service/register.html b/prediction_service/templates/prediction_service/register.html index fab6ea9100e829843fc6442b942a452dc31e6d3a..ca1b2cc03e158851bc648ad5333a14a4b589c5bc 100644 --- a/prediction_service/templates/prediction_service/register.html +++ b/prediction_service/templates/prediction_service/register.html @@ -8,14 +8,15 @@ <h1>MLAAS Register</h1> <form action="/register/" method="post"> {% csrf_token %} - <fieldset class="form-group"> - <legend class="border-bottom mb-4">Join Today!</legend> - {{ form.as_p }} - </fieldset> - <div class="form-group"> - <button class="btn btn-outline-info" type="submit">Sign Up</button> - </div> + <fieldset class="form-group"> + <legend class="border-bottom mb-4">Join Today!</legend> + {{ form.as_p }} + </fieldset> + <div class="form-group"> + <button class="btn btn-outline-info" type="submit">Sign Up</button> + </div> </form> + <div class="border-top pt-3"> <small class="text-muted"> diff --git a/prediction_service/urls.py b/prediction_service/urls.py index 154dbe9491aecdf6014a175ecd3d54a41f0e453a..e537584696ca2c5bf0ab1d9685de0c64782ee74f 100644 --- a/prediction_service/urls.py +++ b/prediction_service/urls.py @@ -2,12 +2,14 @@ from django.urls import path from . import views from django.contrib.auth import views as auth_views +from .views import MLAAS_login + urlpatterns = [ path('', auth_views.LoginView.as_view(template_name='prediction_service/login.html'), name='MLAAS-login'), path('register/', views.register, name='MLAAS-register'), - path('login/', auth_views.LoginView.as_view(template_name='prediction_service/login.html'), name='MLAAS-login'), # + path('login/', MLAAS_login, name='MLAAS-login'), # path('logout/', auth_views.LogoutView.as_view(template_name='prediction_service/logout.html'), name='MLAAS-logout'), # path('about/', views.about, name='MLAAS-about'), diff --git a/prediction_service/views.py b/prediction_service/views.py index 8883186b774deabe8a00da7f96741809301b7f23..cfeffc6eb739deb9380100a5cd449e33a39d5756 100644 --- a/prediction_service/views.py +++ b/prediction_service/views.py @@ -28,24 +28,65 @@ def about(request): return render(request, 'prediction_service/about.html', {'title':'About'}) -def register(request): +from django.contrib import messages +from .forms import UserRegisterForm +from .models import UserProfile, EndUser, AIEngineer +def register(request): if request.method == "POST": - form = UserRegisterForm(request.POST) #fill whatever form we have with current form input - + form = UserRegisterForm(request.POST) if form.is_valid(): - - form.save() # save the user account to the db - - username = form.cleaned_data.get('username')# uses the data and clears it from form + user = form.save() + username = form.cleaned_data.get('username') + role = form.cleaned_data.get('role') + + # Create UserProfile + user_profile = UserProfile.objects.create(user=user, role=role) + + # Create EndUser if role is 'user' + if role == 'user': + EndUser.objects.create(user=user_profile) + elif role == 'ai_engineer': + AIEngineer.objects.create(user=user_profile, is_authorized=False) + messages.success(request, f'Account created for {username}!') return redirect('MLAAS-login') else: form = UserRegisterForm() - - # if metho is GET then return normal register page return render(request, 'prediction_service/register.html', {'form': form}) + +from django.contrib.auth import authenticate, login + +from django.contrib import messages +from django.shortcuts import render, redirect +from django.contrib.auth import authenticate, login +from .models import AIEngineer + +def MLAAS_login(request): + if request.method == "POST": + username = request.POST.get('username') + password = request.POST.get('password') + user = authenticate(request, username=username, password=password) + + if user is not None: + if user.userprofile.role == 'ai_engineer': + ai_engineer = AIEngineer.objects.get(user=user.userprofile) + if not ai_engineer.is_authorized: + messages.error(request, 'You are not authorized to access the MLaaS system. Please wait for admin authorization.') + return redirect('MLAAS-login') # Redirect to login page + + login(request, user) + return redirect('MLAAS-home') + + else: + messages.error(request, 'Invalid username or password.') + return redirect('MLAAS-login') # Redirect to login page if login fails + + return render(request, 'prediction_service/login.html') + + + import os import io import numpy as np