from odoo.tests.common import TransactionCase, HttpCase from odoo.exceptions import AccessError class TestLibrarySecurity(TransactionCase): def setUp(self): super(TestLibrarySecurity, self).setUp() # Ensure portal user exists self.portal_user = self.env['res.users'].search([('login', '=', 'portal_test')], limit=1) if not self.portal_user: self.portal_user = self.env['res.users'].create({ 'name': 'Portal User', 'login': 'portal_test', 'group_ids': [(4, self.env.ref('base.group_portal').id)] }) self.portal_user2 = self.env['res.users'].create({ 'name': 'Portal User 2', 'login': 'portal_test2', 'group_ids': [(4, self.env.ref('base.group_portal').id)] }) self.library = self.env['education.library'].create({ 'name': 'Main Library Sec', 'code': 'MLS01' }) self.company = self.env.company self.campus = self.env['education.campus'].create({ 'name': 'Test Campus Sec', 'code': 'TCS01', 'company_id': self.company.id, }) self.level = self.env['education.academic.level'].create({ 'name': 'UG Sec', 'code': 'UGS01', 'company_id': self.company.id, }) self.department = self.env['education.department'].create({ 'name': 'Test Department Sec', 'code': 'TDS01', 'campus_id': self.campus.id, }) self.academic_year = self.env['education.academic.year'].create({ 'name': '2025-2026 Sec', 'code': 'AY2025S', 'start_date': '2025-06-01', 'end_date': '2026-05-31', 'company_id': self.company.id, 'state': 'draft', }) self.academic_term = self.env['education.academic.term'].create({ 'name': 'Sem 1 Sec', 'code': 'SEM1S', 'academic_year_id': self.academic_year.id, 'start_date': '2025-06-01', 'end_date': '2025-09-30', 'sequence': 1, 'company_id': self.company.id, }) self.program = self.env['education.program'].create({ 'name': 'BTech CS Sec', 'code': 'BTECH-CSS', 'level_id': self.level.id, 'department_id': self.department.id, 'duration': 4, 'duration_unit': 'years', 'company_id': self.company.id, }) self.batch = self.env['education.batch'].create({ 'name': 'Batch 2025 Sec', 'code': 'B2025S', }) self.semester = self.env['education.semester'].create({ 'name': 'Semester 1 Sec', 'code': 'SEM1S', }) self.section = self.env['education.section'].create({ 'name': 'Section A Sec', 'code': 'SEC-AS', }) self.student = self.env['education.student'].create({ 'first_name': 'Portal', 'last_name': 'Student', 'admission_number': 'SEC001', 'portal_user_id': self.portal_user.id, 'campus_id': self.campus.id, 'department_id': self.department.id, 'program_id': self.program.id, 'level_id': self.level.id, 'academic_year_id': self.academic_year.id, 'academic_term_id': self.academic_term.id, 'batch_id': self.batch.id, 'semester_id': self.semester.id, 'section_id': self.section.id, 'company_id': self.company.id, }) self.student2 = self.env['education.student'].create({ 'first_name': 'Portal2', 'last_name': 'Student2', 'admission_number': 'SEC002', 'portal_user_id': self.portal_user2.id, 'campus_id': self.campus.id, 'department_id': self.department.id, 'program_id': self.program.id, 'level_id': self.level.id, 'academic_year_id': self.academic_year.id, 'academic_term_id': self.academic_term.id, 'batch_id': self.batch.id, 'semester_id': self.semester.id, 'section_id': self.section.id, 'company_id': self.company.id, }) self.member1 = self.env['education.library.member'].create({ 'member_number': 'SM001', 'student_id': self.student.id, 'library_id': self.library.id, 'user_id': self.portal_user.id }) self.member2 = self.env['education.library.member'].create({ 'member_number': 'SM002', 'student_id': self.student2.id, 'library_id': self.library.id, 'user_id': self.portal_user2.id }) self.book = self.env['education.library.book'].create({ 'title': 'Security Book', 'author': 'Auth', }) self.copy = self.env['education.library.book.copy'].create({ 'book_id': self.book.id, 'library_id': self.library.id, 'accession_number': 'SEC-001' }) self.issue1 = self.env['education.library.issue'].create({ 'member_id': self.member1.id, 'copy_id': self.copy.id, 'status': 'issued' }) def test_student_cannot_read_others_issue(self): # As portal user 2, try to read issue 1 with self.assertRaises(AccessError): self.issue1.with_user(self.portal_user2).read(['name']) def test_student_can_read_own_issue(self): # Should not raise exception self.issue1.with_user(self.portal_user).read(['name']) def test_student_cannot_spoof_member(self): # Portal user 1 trying to create an issue for Member 2 with self.assertRaises(AccessError): self.env['education.library.issue'].with_user(self.portal_user).create({ 'member_id': self.member2.id, 'copy_id': self.copy.id })