Skip to content

Commit

Permalink
Fix part of #19435: Migrate Blog Admin page (#19471)
Browse files Browse the repository at this point in the history
* Make blog-admin backend migration changes

* Create blog admin route guard and remove redundant file

* Create blog-admin-page root component and remove downgrading

* Update blog-admin-page module

* Update blog-admin module components

* Update app routing and webpack configuration

* Fix linting issues

* Fix linting issues

* Fix incorrect file overview

* Remove BLOG_ADMIN_PAGE_URL from feconf

* Fix blog admin page not having navbar
  • Loading branch information
Vir-8 committed Jan 17, 2024
1 parent 55bb94a commit 10abdcc
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 150 deletions.
18 changes: 18 additions & 0 deletions assets/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7113,6 +7113,24 @@ export default {
}
]
},
"BLOG_ADMIN": {
"ROUTE": "blog-admin",
"TITLE": "Oppia Blog Admin Panel",
"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."
}
]
},
"LEARNER_GROUP_VIEWER": {
"ROUTE": "learner-group/:learner_group_id",
"TITLE": "I18N_LEARNER_GROUP_PAGE_TITLE",
Expand Down
13 changes: 0 additions & 13 deletions core/controllers/blog_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,6 @@
BLOG_ADMIN: Final = feconf.ROLE_ID_BLOG_ADMIN


class BlogAdminPage(base.BaseHandler[Dict[str, str], Dict[str, str]]):
"""Blog Admin Page Handler to render the frontend template."""

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

@acl_decorators.can_access_blog_admin_page
def get(self) -> None:
"""Handles GET requests."""

self.render_template('blog-admin-page.mainpage.html')


class BlogAdminHandlerNormalizedPayloadDict(TypedDict):
"""Dict representation of BlogAdminHandler's normalized_payload
dictionary.
Expand Down
22 changes: 0 additions & 22 deletions core/controllers/blog_admin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,6 @@
from core.tests import test_utils


class BlogAdminPageTests(test_utils.GenericTestBase):
"""Checks the access to the blog admin page and its rendering."""

def test_blog_admin_page_access_without_logging_in(self) -> None:
"""Tests access to the Blog Admin page."""
self.get_html_response('/blog-admin', expected_status_int=302)

def test_blog_admin_page_acess_without_being_blog_admin(self) -> None:
self.signup(self.VIEWER_EMAIL, self.VIEWER_USERNAME)
self.login(self.VIEWER_EMAIL)
self.get_html_response('/blog-admin', expected_status_int=401)
self.logout()

def test_blog_admin_page_acess_as_blog_admin(self) -> None:
self.signup(self.BLOG_ADMIN_EMAIL, self.BLOG_ADMIN_USERNAME)
self.add_user_role(
self.BLOG_ADMIN_USERNAME, feconf.ROLE_ID_BLOG_ADMIN)
self.login(self.BLOG_ADMIN_EMAIL)
self.get_html_response('/blog-admin')
self.logout()


class BlogAdminRolesHandlerTest(test_utils.GenericTestBase):
"""Checks the user role handling on the blog admin page."""

Expand Down
1 change: 0 additions & 1 deletion core/feconf.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,6 @@ def get_empty_ratings() -> Dict[str, int]:
ABOUT_FOUNDATION_PAGE_URL = '/about-foundation'
ADMIN_URL = '/admin'
ADMIN_ROLE_HANDLER_URL = '/adminrolehandler'
BLOG_ADMIN_PAGE_URL = '/blog-admin'
CLASSROOM_ADMIN_PAGE_URL = '/classroom-admin'
BLOG_ADMIN_ROLE_HANDLER_URL = '/blogadminrolehandler'
BLOG_DASHBOARD_DATA_URL = '/blogdashboardhandler/data'
Expand Down
85 changes: 85 additions & 0 deletions core/templates/pages/blog-admin-page/blog-admin-auth.guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// 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 Tests for BlogAdminAuthGuard
*/

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 { BlogAdminAuthGuard } from './blog-admin-auth.guard';

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

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

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

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

it('should redirect user to 401 page if user is not blog 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 blog admin', (done) => {
const getUserInfoAsyncSpy = spyOn(
userService, 'getUserInfoAsync').and.returnValue(
Promise.resolve(new UserInfo(
['BLOG_ADMIN'], false, false, false, 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();
});
});
});
58 changes: 58 additions & 0 deletions core/templates/pages/blog-admin-page/blog-admin-auth.guard.ts
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 blog 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 BlogAdminAuthGuard 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.isBlogAdmin()) {
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,4 @@
<oppia-angular-root>
<oppia-blog-admin-navbar></oppia-blog-admin-navbar>
<oppia-blog-admin-page></oppia-blog-admin-page>
</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 blog admin 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 { BlogAdminPageRootComponent } from './blog-admin-page-root.component';

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

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

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

it('should have the title and meta tags set', () => {
expect(component.title).toEqual(
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.BLOG_ADMIN.TITLE);
expect(component.meta).toEqual(
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.BLOG_ADMIN.META);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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 Blog admin page root component.
*/

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

@Component({
selector: 'oppia-blog-admin-page-root',
templateUrl: './blog-admin-page-root.component.html',
})
export class BlogAdminPageRootComponent extends BaseRootComponent {
title: string = AppConstants.PAGES_REGISTERED_WITH_FRONTEND.BLOG_ADMIN.TITLE;
meta: MetaTagData[] =
AppConstants.PAGES_REGISTERED_WITH_FRONTEND.BLOG_ADMIN.META as
unknown as Readonly<MetaTagData>[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
*/

import { Component, OnInit } from '@angular/core';
import { downgradeComponent } from '@angular/upgrade/static';

import { BlogAdminBackendApiService, PlatformParameterBackendResponse, PlatformParameterValues }
from 'domain/blog-admin/blog-admin-backend-api.service';
import { BlogAdminDataService } from 'pages/blog-admin-page/services/blog-admin-data.service';
Expand Down Expand Up @@ -182,7 +180,3 @@ export class BlogAdminPageComponent implements OnInit {
});
}
}

angular.module('oppia').directive(
'oppiaBlogAdminPage', downgradeComponent(
{component: BlogAdminPageComponent}));
18 changes: 0 additions & 18 deletions core/templates/pages/blog-admin-page/blog-admin-page.mainpage.html

This file was deleted.

Loading

0 comments on commit 10abdcc

Please sign in to comment.