Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #19435: Migrate Email Dashboard #19627

Merged
merged 24 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c5a1f4a
email dashboard page added among the pages registered with frontend
sagar-subedi Jan 26, 2024
33bd7fc
handler for email dashboard removed from backend
sagar-subedi Jan 27, 2024
5190e00
removed backend test for email dashbard page
sagar-subedi Jan 28, 2024
dc084b2
removed link with old handler
sagar-subedi Jan 28, 2024
ba494f9
redundant mainpage file deleted
sagar-subedi Jan 28, 2024
a42196b
added auth guard for email dashboard
sagar-subedi Jan 28, 2024
9dc0e39
removed downgrading of email dashboard page
sagar-subedi Jan 28, 2024
9988bd4
added root component for email dashboard
sagar-subedi Jan 28, 2024
89416a4
updated module for email dashboard
sagar-subedi Jan 28, 2024
f0b82fa
added to the app routing module
sagar-subedi Jan 28, 2024
2a14bb1
removed email dashboard module from webpack configuration
sagar-subedi Jan 28, 2024
6482e88
fixed linter errors
sagar-subedi Jan 29, 2024
bff0e7d
linter checks fixed
sagar-subedi Jan 29, 2024
006d21d
navbar added to the email dashboard page
sagar-subedi Jan 29, 2024
eab914f
test added for auth guard and root component of email dashboard
sagar-subedi Jan 29, 2024
12f2f7b
removed redundant backend test case as the page is migrated to frontend
sagar-subedi Jan 30, 2024
ef1f1c9
added css to the root page component
sagar-subedi Jan 30, 2024
1a37c71
style moved to the top to follow the existing standard
sagar-subedi Jan 31, 2024
2054eae
updated 2023 to 2024 in copyright disclaimer
sagar-subedi Jan 31, 2024
9eb7ba0
Merge branch 'develop' into email-dashboard-migration
sagar-subedi Feb 1, 2024
b545d40
Merge branch 'develop' into email-dashboard-migration
sagar-subedi Feb 10, 2024
e4ce9b1
updated test description
sagar-subedi Feb 11, 2024
efc23ef
Merge branch 'email-dashboard-migration' of https://github.com/sagar-…
sagar-subedi Feb 11, 2024
60c0e02
Merge branch 'develop' into email-dashboard-migration
sagar-subedi Feb 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions assets/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6602,6 +6602,24 @@ export default {
}
]
},
"EMAIL_DASHBOARD": {
"ROUTE": "emaildashboard",
"TITLE": "Email Dashboard - Oppia",
"META": [
{
"PROPERTY_TYPE": "itemprop",
"PROPERTY_VALUE": "description",
// eslint-disable-next-line max-len
"CONTENT": "With Oppia, you can access free lessons on math, physics, statistics, chemistry, music, history and more from anywhere in the world. Oppia is a nonprofit with the mission of providing high-quality education to those who lack access to it."
},
{
"PROPERTY_TYPE": "itemprop",
"PROPERTY_VALUE": "og:description",
// eslint-disable-next-line max-len
"CONTENT": "With Oppia, you can access free lessons on math, physics, statistics, chemistry, music, history and more from anywhere in the world. Oppia is a nonprofit with the mission of providing high-quality education to those who lack access to it."
}
]
},
"MODERATOR": {
"ROUTE": "moderator",
"TITLE": "Moderator Tools - Oppia",
Expand Down
14 changes: 0 additions & 14 deletions core/controllers/email_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,6 @@
num_qualified_users: int


class EmailDashboardPage(
base.BaseHandler[Dict[str, str], Dict[str, str]]
):
"""Page to submit query and show past queries."""

URL_PATH_ARGS_SCHEMAS: Dict[str, str] = {}
HANDLER_ARGS_SCHEMAS: Dict[str, Dict[str, str]] = {'GET': {}}

@acl_decorators.can_manage_email_dashboard
def get(self) -> None:
"""Handles GET requests."""
self.render_template('email-dashboard-page.mainpage.html')


def _generate_user_query_dicts(
user_queries: List[user_query_domain.UserQuery]
) -> List[UserQueryDict]:
Expand Down Expand Up @@ -213,7 +199,7 @@

user_query = user_query_services.get_user_query(query_id)
if user_query is None:
raise self.InvalidInputException('Invalid query id.')

Check failure on line 202 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

Invalid query id.

Check failure on line 202 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

Invalid query id.

data = {
'query': _generate_user_query_dicts([user_query])[0]
Expand Down Expand Up @@ -280,7 +266,7 @@
user_query is None or
user_query.status != feconf.USER_QUERY_STATUS_COMPLETED
):
raise self.InvalidInputException('400 Invalid query id.')

Check failure on line 269 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

Check failure on line 269 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

if user_query.submitter_id != self.user_id:
raise self.UnauthorizedUserException(
Expand All @@ -296,7 +282,7 @@
user_query is None or
user_query.status != feconf.USER_QUERY_STATUS_COMPLETED
):
raise self.InvalidInputException('400 Invalid query id.')

Check failure on line 285 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

Check failure on line 285 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

if user_query.submitter_id != self.user_id:
raise self.UnauthorizedUserException(
Expand Down Expand Up @@ -332,7 +318,7 @@
user_query is None or
user_query.status != feconf.USER_QUERY_STATUS_COMPLETED
):
raise self.InvalidInputException('400 Invalid query id.')

Check failure on line 321 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

Check failure on line 321 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

if user_query.submitter_id != self.user_id:
raise self.UnauthorizedUserException(
Expand Down Expand Up @@ -392,7 +378,7 @@
user_query is None or
user_query.status != feconf.USER_QUERY_STATUS_COMPLETED
):
raise self.InvalidInputException('400 Invalid query id.')

Check failure on line 381 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

Check failure on line 381 in core/controllers/email_dashboard.py

View workflow job for this annotation

GitHub Actions / Run backend tests (ubuntu-22.04, 1)

400 Invalid query id.

if user_query.submitter_id != self.user_id:
raise self.UnauthorizedUserException(
Expand Down
8 changes: 0 additions & 8 deletions core/controllers/email_dashboard_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,6 @@ def test_starting_job(self) -> None:

self.logout()

def test_email_dashboard_page(self) -> None:
self.login(self.SUBMITTER_EMAIL, is_super_admin=True)

response = self.get_html_response('/emaildashboard')
self.assertIn(b'{"title": "Email Dashboard - Oppia"})', response.body)

self.logout()


class EmailDashboardResultTests(test_utils.EmailTestBase):
"""Tests for email dashboard result handler."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright 2023 The Oppia Authors. All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright 2024..
Please update this to 2024 and ditto elsewhere

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @fileoverview Tests for EmailDashboardAuthGuard
*/

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, NavigationExtras } from '@angular/router';

import { AppConstants } from '../../app.constants';
import { UserInfo } from '../../domain/user/user-info.model';
import { UserService } from '../../services/user.service';
import { EmailDashboardAuthGuard } from './email-dashboard-auth.guard';


class MockRouter {
navigate(commands: string[], extras?: NavigationExtras): Promise<boolean> {
return Promise.resolve(true);
}
}

describe('EmailDashboardAuthGuard', () => {
let userService: UserService;
let router: Router;
let guard: EmailDashboardAuthGuard;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [UserService, { provide: Router, useClass: MockRouter }],
}).compileComponents();

guard = TestBed.inject(EmailDashboardAuthGuard);
userService = TestBed.inject(UserService);
router = TestBed.inject(Router);
});

it('should redirect user to 401 page if user is not super admin', (done) => {
const getUserInfoAsyncSpy = spyOn(
userService, 'getUserInfoAsync').and.returnValue(
Promise.resolve(UserInfo.createDefault())
);
const navigateSpy = spyOn(router, 'navigate').and.callThrough();

guard.canActivate(
new ActivatedRouteSnapshot(), {} as RouterStateSnapshot).then(
(canActivate) => {
expect(canActivate).toBeFalse();
expect(getUserInfoAsyncSpy).toHaveBeenCalledTimes(1);
expect(navigateSpy).toHaveBeenCalledWith([
`${AppConstants.PAGES_REGISTERED_WITH_FRONTEND.ERROR.ROUTE}/401`]);
done();
});
});

it('should not redirect user to 401 page if user is super admin', (done) => {
Copy link
Member

@Nik-09 Nik-09 Feb 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename this test case to something around -- should access the email dashboard page if the user is super admin.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

const getUserInfoAsyncSpy = spyOn(
userService, 'getUserInfoAsync').and.returnValue(
Promise.resolve(new UserInfo(
[], false, false, true, false, false, '', '', '', true))
);
const navigateSpy = spyOn(router, 'navigate').and.callThrough();

guard.canActivate(
new ActivatedRouteSnapshot(), {} as RouterStateSnapshot).then(
(canActivate) => {
expect(canActivate).toBeTrue();
expect(getUserInfoAsyncSpy).toHaveBeenCalledTimes(1);
expect(navigateSpy).not.toHaveBeenCalled();
done();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2023 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @fileoverview Guard that redirects user to 401 error page
* if the user is not a super admin.
*/

import { Location } from '@angular/common';
import { Injectable } from '@angular/core';
import {
ActivatedRouteSnapshot,
CanActivate,
Router,
RouterStateSnapshot,
} from '@angular/router';

import { AppConstants } from 'app.constants';
import { UserService } from 'services/user.service';

@Injectable({
providedIn: 'root'
})
export class EmailDashboardAuthGuard implements CanActivate {
constructor(
private userService: UserService,
private router: Router,
private location: Location
) {}

async canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Promise<boolean> {
const userInfo = await this.userService.getUserInfoAsync();
if (userInfo.isSuperAdmin()) {
return true;
}

this.router.navigate(
[`${AppConstants.PAGES_REGISTERED_WITH_FRONTEND
.ERROR.ROUTE}/401`]).then(() => {
this.location.replaceState(state.url);
});
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<oppia-angular-root>
<oppia-base-content>
<navbar-breadcrumb>
<ul class="nav navbar-nav oppia-navbar-breadcrumb">
<li>
<span class="oppia-navbar-breadcrumb-separator"></span>
Email Dashboard
</li>
</ul>
</navbar-breadcrumb>
<content>
<oppia-email-dashboard-page></oppia-email-dashboard-page>
</content>
<page-footer></page-footer>
</oppia-base-content>
</oppia-angular-root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2023 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @fileoverview Unit tests for Email Dashboard Page Root component.
*/

import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';

import { AppConstants } from '../../app.constants';
import { PageHeadService } from '../../services/page-head.service';
import { EmailDashboardPageRootComponent } from './email-dashboard-page-root.component';

describe('EmailDashboardPageRootComponent', () => {
let fixture: ComponentFixture<EmailDashboardPageRootComponent>;
let component: EmailDashboardPageRootComponent;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), HttpClientTestingModule],
declarations: [EmailDashboardPageRootComponent],
providers: [PageHeadService],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();

fixture = TestBed.createComponent(EmailDashboardPageRootComponent);
component = fixture.componentInstance;
});

it('should have the title and meta tags set', () => {
expect(component.title).toEqual(
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.EMAIL_DASHBOARD.TITLE);
expect(component.meta).toEqual(
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.EMAIL_DASHBOARD.META);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
* @fileoverview Email Dashboard page root component.
*/

import { Component } from '@angular/core';
import { AppConstants } from 'app.constants';
import { BaseRootComponent, MetaTagData } from 'pages/base-root.component';

@Component({
selector: 'oppia-email-dashboard-page-root',
templateUrl: './email-dashboard-page-root.component.html',
})
export class EmailDashboardPageRootComponent extends BaseRootComponent {
title: string =
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.EMAIL_DASHBOARD.TITLE;

meta: MetaTagData[] =
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.EMAIL_DASHBOARD.META as
unknown as Readonly<MetaTagData>[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/

import { ChangeDetectorRef, Component } from '@angular/core';
import { downgradeComponent } from '@angular/upgrade/static';
import { AppConstants } from 'app.constants';
import { QueryData } from 'domain/email-dashboard/email-dashboard-backend-api.service';
import { EmailDashboardQuery } from 'domain/email-dashboard/email-dashboard-query.model';
Expand Down Expand Up @@ -131,8 +130,3 @@ export class EmailDashboardPageComponent {
return (submitter === this.username) && (status === 'completed');
}
}

angular.module('oppia').directive('oppiaEmailDashboardPage',
downgradeComponent({
component: EmailDashboardPageComponent
}) as angular.IDirectiveFactory);

This file was deleted.

Loading
Loading