From b7f09cced0b2a6912738d761e165d8b7ca5144c9 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Tue, 8 Dec 2020 18:28:15 -0300 Subject: [PATCH 01/15] feat (route): new institution list --- .../Http/v1/InstitutionController.js | 16 ++ .../app/Controllers/Http/v1/UserController.js | 186 +++++++++++------- src/adonisjs/start/routes.js | 11 ++ 3 files changed, 138 insertions(+), 75 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/InstitutionController.js b/src/adonisjs/app/Controllers/Http/v1/InstitutionController.js index 2bf94a9..9d19cba 100644 --- a/src/adonisjs/app/Controllers/Http/v1/InstitutionController.js +++ b/src/adonisjs/app/Controllers/Http/v1/InstitutionController.js @@ -22,6 +22,22 @@ class InstitutionController { return response.status(500).json({ message: e.message }) } } + + async listInstitutions ({ request, response }) { + try { + const institutions = await Institution + .query() + .where('acronym', '!=', 'uni') + .fetch() + + + return response.json(institutions) + } catch (e) { + console.log(e) + return response.status(500).json({ message: e.message }) + } + } + } module.exports = InstitutionController diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index 6e0f919..69a5ef0 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -20,14 +20,14 @@ const Env = use('Env') class UserController { /** - * Show a list of all users. - * GET users - * - * @param {object} ctx - * @param {Request} ctx.request - * @param {Response} ctx.response - * @param {View} ctx.view - */ + * Show a list of all users. + * GET users + * + * @param {object} ctx + * @param {Request} ctx.request + * @param {Response} ctx.response + * @param {View} ctx.view + */ async index ({ request, response, view, auth }) { try { const users = await User.all() @@ -38,14 +38,14 @@ class UserController { } /** - * Display a single user. - * GET users/:id - * - * @param {object} ctx - * @param {Request} ctx.request - * @param {Response} ctx.response - * @param {View} ctx.view - */ + * Display a single user. + * GET users/:id + * + * @param {object} ctx + * @param {Request} ctx.request + * @param {Response} ctx.response + * @param {View} ctx.view + */ async show ({ params, request, response, view }) { try { const user = await User.find(params.id) @@ -58,13 +58,13 @@ class UserController { } /** - * Create/save a new user. - * POST users - * - * @param {object} ctx - * @param {Request} ctx.request - * @param {Response} ctx.response - */ + * Create/save a new user. + * POST users + * + * @param {object} ctx + * @param {Request} ctx.request + * @param {Response} ctx.response + */ async store ({ request, auth, response }) { try { const user = new User() @@ -97,23 +97,23 @@ class UserController { } /** - * Update user details. - * PUT or PATCH users/:id - * - * @param {object} ctx - * @param {Request} ctx.request - * @param {Response} ctx.response - - */ + * Update user details. + * PUT or PATCH users/:id + * + * @param {object} ctx + * @param {Request} ctx.request + * @param {Response} ctx.response + + */ async update ({ params, request, response, auth }) { try { const user = await User.find(auth.user.id) const updatedUser = { - username : request.input('username') || user.username, - email : request.input('email') || user.email, - login : request.input('login') || user.login, - grade : request.input('grade') || user.grade + username : request.input('username') || user.username, + email : request.input('email') || user.email, + login : request.input('login') || user.login, + grade : request.input('grade') || user.grade } if (user != null) { @@ -161,7 +161,7 @@ class UserController { } /** Delete a user with id. - * DELETE user/:id */ + * DELETE user/:id */ async destroy ({ params, response, auth }) { try { const user = await User.find(params.id) @@ -177,7 +177,7 @@ class UserController { } -// @BROKEN + // @BROKEN async list_quests ({ request, response, auth }) { try { const user = await auth.user @@ -197,30 +197,66 @@ class UserController { var publishedFilter = parseInt(request.input('published')) || 0 - request.input('published') != null - // Atualmente retorna somente casos compartilhados com institution, é preciso aumentar a sql pra comportar outros escopos: grupos, only me, system, etc... - // Return cases which the user is author AND cases which she have access permissions - const result = await Database - .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', - 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', - 'cases.author_grade', 'cases.published', 'users.username']) - .distinct('cases.id') - .from('cases') - .leftJoin('permissions', 'cases.id', 'permissions.table_id') - .join('users', 'users.id', 'cases.author_id') - .where('cases.published', '>=', publishedFilter) - .where(function(){ - this - .where('cases.author_id', user.id) - .orWhere(function () { - this - .where('permissions.entity', 'institution') - .where('permissions.subject', user.institution_id) - .where('permissions.clearance', '>=', clearance) - }) - }) - + const institutionFilter = request.input('fInstitution') || `%` + const userTypeFilter = request.input('fUserType') || `%` + console.log('============') + console.log(institutionFilter) + console.log(userTypeFilter) + request.input('published') != null + // request.input('fInstitution') != null + // request.input('fUserType') != null + // Atualmente retorna somente casos compartilhados com institution, é preciso aumentar a sql pra comportar outros escopos: grupos, only me, system, etc... + // Return cases which the user is author AND cases which she have access permissions + // const result = await Database + // .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', + // 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', + // 'cases.author_grade', 'cases.published', 'users.username', + // 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', + // 'institutions.country AS institution_country', 'cases.created_at']) + // .distinct('cases.id') + // .from('cases') + // .leftJoin('permissions', 'cases.id', 'permissions.table_id') + // .join('users', 'users.id', 'cases.author_id') + // .join('institutions', 'users.institution_id', 'institutions.id') + // .where('cases.published', '>=', publishedFilter) + // .where(function(){ + // this + // .where('cases.author_id', user.id) + // .orWhere(function () { + // this + // .where('permissions.entity', 'institution') + // .where('permissions.subject', user.institution_id) + // .where('permissions.clearance', '>=', clearance) + // }) + // }) + // .orderBy('cases.created_at', 'desc') + // + + const result = await Database + .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', + 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', + 'cases.author_grade', 'cases.published', 'users.username', + 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', 'institutions.country AS institution_country', 'cases.created_at']) + .distinct('cases.id') + .from('cases') + .leftJoin('permissions', 'cases.id', 'permissions.table_id') + .join('users', 'users.id', 'cases.author_id') + .join('institutions', 'users.institution_id', 'institutions.id') + .where('cases.published', '>=', publishedFilter) + .where('cases.institution_id', 'like', institutionFilter) + .where('cases.author_grade', 'like', userTypeFilter) + .where(function(){ + this + .where('cases.author_id', user.id) + .orWhere(function () { + this + .where('permissions.entity', 'institution') + .where('permissions.subject', user.institution_id) + .where('permissions.clearance', '>=', clearance) + }) + }) + .orderBy('cases.created_at', 'desc') console.log(result) @@ -232,16 +268,16 @@ class UserController { } -// @broken + // @broken async list_cases_by_quests ({ params, response, auth }) { try { const user = await auth.user Database - .select('*') - .from('quests_users') - .where('user_id', user.id) - .leftJoin('cases', 'quests.case_id', 'cases.id') + .select('*') + .from('quests_users') + .where('user_id', user.id) + .leftJoin('cases', 'quests.case_id', 'cases.id') const quests = await user.quests().fetch() @@ -257,11 +293,11 @@ class UserController { const user = await auth.user const resultQuest = await Database - .select('*') - .from('quests_users') - .where('user_id', user.id) - .whereIn('permission', ['write', 'share', 'delete']) - .leftJoin('quests', 'quests_users.quest_id', 'quests.id') + .select('*') + .from('quests_users') + .where('user_id', user.id) + .whereIn('permission', ['write', 'share', 'delete']) + .leftJoin('quests', 'quests_users.quest_id', 'quests.id') const base_url = Env.getOrFail('APP_URL') const quests = [] @@ -291,11 +327,11 @@ class UserController { const user = await auth.user const resultQuest = await Database - .select('*') - .from('quests_users') - .where('user_id', user.id) - .where('permission', 'read') - .leftJoin('quests', 'quests_users.quest_id', 'quests.id') + .select('*') + .from('quests_users') + .where('user_id', user.id) + .where('permission', 'read') + .leftJoin('quests', 'quests_users.quest_id', 'quests.id') const base_url = Env.getOrFail('APP_URL') const quests = [] diff --git a/src/adonisjs/start/routes.js b/src/adonisjs/start/routes.js index b58b5d8..a4af475 100644 --- a/src/adonisjs/start/routes.js +++ b/src/adonisjs/start/routes.js @@ -140,6 +140,17 @@ Route.group(() => { }).prefix('/api/v1/category').middleware('auth', 'is:author') +/* +|---------------------------------------------------------------------------------------------- +| api: v1 +| resource: /institution +|---------------------------------------------------------------------------------------------- +*/ +Route.group(() => { + + Route.get( '', 'v1/InstitutionController.listInstitutions').middleware(['auth']) +}).prefix('/api/v1/institutions') + /* |---------------------------------------------------------------------------------------------- From 5ee2c20ecf742a9359b7ed9517edc5d8f856c67b Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Wed, 9 Dec 2020 15:26:39 -0300 Subject: [PATCH 02/15] feat (postman): update case list filters --- harena-manager.postman_collection.json | 40 +++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/harena-manager.postman_collection.json b/harena-manager.postman_collection.json index 800d415..28c4727 100644 --- a/harena-manager.postman_collection.json +++ b/harena-manager.postman_collection.json @@ -382,6 +382,18 @@ "value": "\n", "type": "text", "disabled": true + }, + { + "key": "fInstitution", + "value": "c5562bfd-9a94-40f0-b08a-3627e3e417e0", + "type": "text", + "disabled": true + }, + { + "key": "fUserType", + "value": "aluno", + "type": "text", + "disabled": true } ], "options": { @@ -592,7 +604,10 @@ "type": "text", "disabled": true } - ] + ], + "options": { + "formdata": {} + } }, "url": { "raw": "{{api-base-url}}/user", @@ -1655,6 +1670,29 @@ ], "protocolProfileBehavior": {} }, + { + "name": "institution", + "item": [ + { + "name": "/institutions", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{api-base-url}}/institutions", + "host": [ + "{{api-base-url}}" + ], + "path": [ + "institutions" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + }, { "name": "admin", "item": [ From 33ca736571c6675b3491d32eb2944b1d0aeb46aa Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Wed, 9 Dec 2020 17:04:24 -0300 Subject: [PATCH 03/15] feat (categoryController): case list by category with filters --- .../Controllers/Http/v1/CategoryController.js | 28 +++++++++++------ .../app/Controllers/Http/v1/UserController.js | 31 ++----------------- 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js index 7925499..2d08619 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js @@ -76,32 +76,42 @@ class CategoryController { async listCases ({ request, response, auth }) { try { const user = await auth.user + + const clearance = parseInt(request.input('clearance')) const categoryId = request.input('categoryId') const category = await Category.find(categoryId) var publishedFilter = parseInt(request.input('published')) || 0 + const institutionFilter = request.input('fInstitution') || `%` + const userTypeFilter = request.input('fUserType') || `%` const test = await Database .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', - 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', - 'cases.author_grade', 'cases.published', 'users.username']) + 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', + 'cases.author_grade', 'cases.published', 'users.username', + 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', + 'institutions.country AS institution_country', 'cases.created_at']) .distinct('cases.id') .from('cases') .leftJoin('permissions', 'cases.id', 'permissions.table_id') .join('users', 'users.id', 'cases.author_id') + .join('institutions', 'users.institution_id', 'institutions.id') .where('cases.category_id', category.id) .where('cases.published', '>=', publishedFilter) + .where('cases.institution_id', 'like', institutionFilter) + .where('cases.author_grade', 'like', userTypeFilter) .where(function(){ this - .where('cases.author_id', user.id) - .orWhere(function () { - this - .where('permissions.entity', 'institution') - .where('permissions.subject', user.institution_id) - .where('permissions.clearance', '>=', clearance) - }) + .where('cases.author_id', user.id) + .orWhere(function () { + this + .where('permissions.entity', 'institution') + .where('permissions.subject', user.institution_id) + .where('permissions.clearance', '>=', clearance) + }) }) + .orderBy('cases.created_at', 'desc') return response.json(test) } catch (e) { diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index 69a5ef0..ce1d496 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -204,40 +204,13 @@ class UserController { console.log(userTypeFilter) request.input('published') != null - // request.input('fInstitution') != null - // request.input('fUserType') != null - // Atualmente retorna somente casos compartilhados com institution, é preciso aumentar a sql pra comportar outros escopos: grupos, only me, system, etc... - // Return cases which the user is author AND cases which she have access permissions - // const result = await Database - // .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', - // 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', - // 'cases.author_grade', 'cases.published', 'users.username', - // 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', - // 'institutions.country AS institution_country', 'cases.created_at']) - // .distinct('cases.id') - // .from('cases') - // .leftJoin('permissions', 'cases.id', 'permissions.table_id') - // .join('users', 'users.id', 'cases.author_id') - // .join('institutions', 'users.institution_id', 'institutions.id') - // .where('cases.published', '>=', publishedFilter) - // .where(function(){ - // this - // .where('cases.author_id', user.id) - // .orWhere(function () { - // this - // .where('permissions.entity', 'institution') - // .where('permissions.subject', user.institution_id) - // .where('permissions.clearance', '>=', clearance) - // }) - // }) - // .orderBy('cases.created_at', 'desc') - // const result = await Database .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', 'cases.author_grade', 'cases.published', 'users.username', - 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', 'institutions.country AS institution_country', 'cases.created_at']) + 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', + 'institutions.country AS institution_country', 'cases.created_at']) .distinct('cases.id') .from('cases') .leftJoin('permissions', 'cases.id', 'permissions.table_id') From 814e58dd420b1f3d961956af6702a1e8505f71ec Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Thu, 10 Dec 2020 23:33:21 -0300 Subject: [PATCH 04/15] feat (routes): share case route --- .../app/Controllers/Http/v1/CaseController.js | 40 +++++++++++++++++++ .../app/Controllers/Http/v1/UserController.js | 6 +-- src/adonisjs/start/routes.js | 1 + 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/CaseController.js b/src/adonisjs/app/Controllers/Http/v1/CaseController.js index c888f63..0be54cc 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CaseController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CaseController.js @@ -198,6 +198,46 @@ class CaseController { } } + async share ({params, request, response}){ + const trx = await Database.beginTransaction() + + try { + const entity = request.input('entity') + const subject = request.input('subject') + const clearance = request.input('clearance') + const table_id = request.input('table_id').split(',') + console.log(entity) + console.log(subject) + console.log(clearance) + console.log(table_id) + + for (let c in table_id){ + console.log('============ case for') + console.log(table_id[c]) + if(await Case.findBy('id', table_id[c])){ + console.log('================================================ case added') + console.log(table_id[c]) + let permission = new Permission() + permission.id = await uuidv4() + permission.entity = entity + permission.subject = subject + permission.clearance = clearance + permission.table = 'cases' + permission.table_id = table_id[c] + await permission.save(trx) + }else return response.json('Could not find the case id, please review and try again') + } + + trx.commit() + return response.json('Cases shared successfully!') + } catch (e) { + trx.rollback() + console.log(e) + return response.status(500).json({ message: e.message }) + } + + } + } module.exports = CaseController diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index ce1d496..a2b63a7 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -199,9 +199,9 @@ class UserController { const institutionFilter = request.input('fInstitution') || `%` const userTypeFilter = request.input('fUserType') || `%` - console.log('============') - console.log(institutionFilter) - console.log(userTypeFilter) + // console.log('============') + // console.log(institutionFilter) + // console.log(userTypeFilter) request.input('published') != null diff --git a/src/adonisjs/start/routes.js b/src/adonisjs/start/routes.js index a4af475..656d7e8 100644 --- a/src/adonisjs/start/routes.js +++ b/src/adonisjs/start/routes.js @@ -68,6 +68,7 @@ Route.group(() => { Route.post( '', 'v1/CaseController.store') Route.put( ':id', 'v1/CaseController.update').middleware(['case_permission:write']) Route.delete(':id', 'v1/CaseController.destroy').middleware(['case_permission:delete']) + Route.post('share', 'v1/CaseController.share').middleware(['case_permission:share']) }).prefix('/api/v1/case').middleware(['auth', 'is:author']) Route.get( '/api/v1/case/:id', 'v1/CaseController.show').middleware(['auth', 'case_permission:read']) From 95a242fbfc6f13fdf0c0ce8c78a544fa9895de43 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Thu, 10 Dec 2020 23:33:50 -0300 Subject: [PATCH 05/15] feat (postman): new share case and endpoint update --- harena-manager.postman_collection.json | 72 ++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/harena-manager.postman_collection.json b/harena-manager.postman_collection.json index 28c4727..05eb5f6 100644 --- a/harena-manager.postman_collection.json +++ b/harena-manager.postman_collection.json @@ -374,12 +374,12 @@ "formdata": [ { "key": "clearance", - "value": "4", + "value": "1", "type": "text" }, { "key": "published", - "value": "\n", + "value": "", "type": "text", "disabled": true }, @@ -988,6 +988,50 @@ } }, "response": [] + }, + { + "name": "/share", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "entity", + "value": "institution", + "type": "text" + }, + { + "key": "subject", + "value": "c5562bfd-9a94-40f0-b08a-3627e3e417e0", + "type": "text" + }, + { + "key": "clearance", + "value": "4", + "type": "text" + }, + { + "key": "table_id", + "value": "e6535d2e-28d9-4493-b61d-c715f56f812f", + "description": "Separate by comma if you want multiple ids", + "type": "text" + } + ] + }, + "url": { + "raw": "{{api-base-url}}/case/share", + "host": [ + "{{api-base-url}}" + ], + "path": [ + "case", + "share" + ] + } + }, + "response": [] } ], "protocolProfileBehavior": {} @@ -1484,8 +1528,30 @@ "formdata": [ { "key": "categoryId", - "value": "decisoesExtremas", + "value": "quiz-da-emergencia", "type": "text" + }, + { + "key": "clearance", + "value": "4", + "type": "text" + }, + { + "key": "published", + "value": "", + "type": "text", + "disabled": true + }, + { + "key": "fInstitution", + "value": "c5562bfd-9a94-40f0-b08a-3627e3e417e0", + "type": "text" + }, + { + "key": "fUserType", + "value": "aluno", + "type": "text", + "disabled": true } ], "options": { From 13db52c64acde0fd5aecb2f4ce8d16bc419e60a8 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Fri, 11 Dec 2020 14:00:54 -0300 Subject: [PATCH 06/15] refactor(CaseController): comment unnecessary logs --- .../app/Controllers/Http/v1/CaseController.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/CaseController.js b/src/adonisjs/app/Controllers/Http/v1/CaseController.js index 0be54cc..00eb769 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CaseController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CaseController.js @@ -206,17 +206,17 @@ class CaseController { const subject = request.input('subject') const clearance = request.input('clearance') const table_id = request.input('table_id').split(',') - console.log(entity) - console.log(subject) - console.log(clearance) - console.log(table_id) + // console.log(entity) + // console.log(subject) + // console.log(clearance) + // console.log(table_id) for (let c in table_id){ - console.log('============ case for') + // console.log('============ case for') console.log(table_id[c]) if(await Case.findBy('id', table_id[c])){ - console.log('================================================ case added') - console.log(table_id[c]) + // console.log('================================================ case added') + // console.log(table_id[c]) let permission = new Permission() permission.id = await uuidv4() permission.entity = entity From 9e834224cbbf0c1c3dad79f4f77c4b6855e509ac Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Sat, 9 Jan 2021 13:44:49 -0300 Subject: [PATCH 07/15] feat (filter cases): add specialty filter --- src/adonisjs/app/Controllers/Http/v1/CategoryController.js | 4 ++++ src/adonisjs/app/Controllers/Http/v1/UserController.js | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js index 2d08619..c83de17 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js @@ -83,8 +83,11 @@ class CategoryController { const category = await Category.find(categoryId) var publishedFilter = parseInt(request.input('published')) || 0 + const institutionFilter = request.input('fInstitution') || `%` const userTypeFilter = request.input('fUserType') || `%` + const specialtyFilter = request.input('fSpecialty') || `%` + const test = await Database .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', @@ -101,6 +104,7 @@ class CategoryController { .where('cases.published', '>=', publishedFilter) .where('cases.institution_id', 'like', institutionFilter) .where('cases.author_grade', 'like', userTypeFilter) + .where('cases.specialty', 'like', specialtyFilter) .where(function(){ this .where('cases.author_id', user.id) diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index a2b63a7..02085e2 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -199,6 +199,7 @@ class UserController { const institutionFilter = request.input('fInstitution') || `%` const userTypeFilter = request.input('fUserType') || `%` + const specialtyFilter = request.input('fSpecialty') || `%` // console.log('============') // console.log(institutionFilter) // console.log(userTypeFilter) @@ -219,6 +220,8 @@ class UserController { .where('cases.published', '>=', publishedFilter) .where('cases.institution_id', 'like', institutionFilter) .where('cases.author_grade', 'like', userTypeFilter) + .where('cases.specialty', 'like', specialtyFilter) + .where(function(){ this .where('cases.author_id', user.id) From 987be5121ff293a9948761a9ab837a166447f3bb Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Mon, 11 Jan 2021 19:28:15 -0300 Subject: [PATCH 08/15] fix (filter cases): fix query specialty filter --- .../app/Controllers/Http/v1/CategoryController.js | 8 ++++++-- src/adonisjs/app/Controllers/Http/v1/UserController.js | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js index c83de17..233f8da 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js @@ -83,7 +83,7 @@ class CategoryController { const category = await Category.find(categoryId) var publishedFilter = parseInt(request.input('published')) || 0 - + const institutionFilter = request.input('fInstitution') || `%` const userTypeFilter = request.input('fUserType') || `%` const specialtyFilter = request.input('fSpecialty') || `%` @@ -104,7 +104,11 @@ class CategoryController { .where('cases.published', '>=', publishedFilter) .where('cases.institution_id', 'like', institutionFilter) .where('cases.author_grade', 'like', userTypeFilter) - .where('cases.specialty', 'like', specialtyFilter) + .where(function(){ + if (specialtyFilter != '%') + this.where('cases.specialty', 'like', specialtyFilter) + }) + .where(function(){ this .where('cases.author_id', user.id) diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index 02085e2..13e2919 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -220,8 +220,11 @@ class UserController { .where('cases.published', '>=', publishedFilter) .where('cases.institution_id', 'like', institutionFilter) .where('cases.author_grade', 'like', userTypeFilter) - .where('cases.specialty', 'like', specialtyFilter) - + .where(function(){ + if (specialtyFilter != '%') + this.where('cases.specialty', 'like', specialtyFilter) + }) + .where(function(){ this .where('cases.author_id', user.id) From 0a4fb392ce5747698171d0d6e9eec44a1725f041 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Mon, 11 Jan 2021 19:40:02 -0300 Subject: [PATCH 09/15] feat (postman): new specialty filter --- harena-manager.postman_collection.json | 252 ++++++------------------- 1 file changed, 60 insertions(+), 192 deletions(-) diff --git a/harena-manager.postman_collection.json b/harena-manager.postman_collection.json index 05eb5f6..313acf4 100644 --- a/harena-manager.postman_collection.json +++ b/harena-manager.postman_collection.json @@ -17,7 +17,6 @@ { "listen": "test", "script": { - "id": "7e4ca188-f483-438b-92e4-faabcb68e232", "exec": [ "var response = pm.response.json();", "pm.environment.set(\"user-token\", response.token);", @@ -53,10 +52,7 @@ "type": "text", "disabled": true } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/auth/login/", @@ -78,7 +74,6 @@ { "listen": "test", "script": { - "id": "4d239fcd-b358-47f3-874b-0f0fe8eb2be6", "exec": [ "" ], @@ -101,10 +96,7 @@ "header": [], "body": { "mode": "formdata", - "formdata": [], - "options": { - "formdata": {} - } + "formdata": [] }, "url": { "raw": "{{api-base-url}}/auth/logout/", @@ -125,7 +117,6 @@ { "listen": "prerequest", "script": { - "id": "7cc84993-51ae-49e5-9d6a-fbcf06c938e3", "type": "text/javascript", "exec": [ "" @@ -135,16 +126,13 @@ { "listen": "test", "script": { - "id": "e8d036f7-f38d-4f12-9350-332845532e2f", "type": "text/javascript", "exec": [ "" ] } } - ], - "protocolProfileBehavior": {}, - "_postman_isSubFolder": true + ] }, { "name": "/auth/login session", @@ -152,7 +140,6 @@ { "listen": "test", "script": { - "id": "62c53a04-7306-4590-ac1f-e0a0415ee3c5", "exec": [ "var response = pm.response.json();", "console.log(response)", @@ -180,10 +167,7 @@ "value": "", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/auth/login", @@ -204,7 +188,6 @@ { "listen": "test", "script": { - "id": "005e1c53-285c-4eb4-a33d-7039ac2a6002", "exec": [ "pm.environment.set(\"user-token\", 'revoked');" ], @@ -250,8 +233,7 @@ "response": [] } ], - "description": "Authentication endpoints", - "protocolProfileBehavior": {} + "description": "Authentication endpoints" }, { "name": "user", @@ -262,7 +244,6 @@ { "listen": "test", "script": { - "id": "8d76235e-2ca8-4773-802b-41b22c5d37c0", "exec": [ "var response = pm.response.json();", "", @@ -291,10 +272,7 @@ "value": "aa9da08a-1bd4-4a57-b4bf-076a889d6046", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/user/cases_by_quest", @@ -315,7 +293,6 @@ { "listen": "test", "script": { - "id": "db6e3ed4-8ce6-44a3-b4da-60fbd5ec5e80", "exec": [ "pm.test(\"Status code is 200\", function () {", " pm.response.to.have.status(200);", @@ -347,7 +324,6 @@ { "listen": "test", "script": { - "id": "ad5da6f0-b5b5-4792-baa7-502b215827c4", "exec": [ "var response = pm.response.json();", "", @@ -374,7 +350,7 @@ "formdata": [ { "key": "clearance", - "value": "1", + "value": "4", "type": "text" }, { @@ -394,11 +370,14 @@ "value": "aluno", "type": "text", "disabled": true + }, + { + "key": "fSpecialty", + "value": "0", + "type": "text", + "disabled": true } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/user/cases", @@ -419,7 +398,6 @@ { "listen": "test", "script": { - "id": "d53aca1e-8cff-4141-bfc2-53fca7af2fa8", "exec": [ "" ], @@ -449,7 +427,6 @@ { "listen": "test", "script": { - "id": "0f147b45-e953-4eda-ac7a-811ca797cd98", "exec": [ "var response = pm.response.json();", "", @@ -473,10 +450,7 @@ "header": [], "body": { "mode": "formdata", - "formdata": [], - "options": { - "formdata": {} - } + "formdata": [] }, "url": { "raw": "{{api-base-url}}/user/cases_by_institution", @@ -497,7 +471,6 @@ { "listen": "test", "script": { - "id": "145c56e0-caff-4d47-8fdf-d2f6905abbdd", "exec": [ "var response = pm.response.json();", "", @@ -550,10 +523,7 @@ "value": "aluno", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/user", @@ -604,10 +574,7 @@ "type": "text", "disabled": true } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/user", @@ -661,7 +628,6 @@ { "listen": "test", "script": { - "id": "dcbba21c-af88-435a-9948-8d03adfac96f", "exec": [ "pm.test(\"Status code is 200 or 204\", function () {", " ", @@ -690,8 +656,7 @@ "response": [] } ], - "description": "User services", - "protocolProfileBehavior": {} + "description": "User services" }, { "name": "case", @@ -720,7 +685,6 @@ { "listen": "test", "script": { - "id": "d358db71-a30f-45df-b924-31f9856e2795", "exec": [ "var response = pm.response.json();", "console.log(response.id)", @@ -814,10 +778,7 @@ "value": "read", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/case", @@ -837,7 +798,6 @@ { "listen": "test", "script": { - "id": "b49b1ec2-2db6-4c3e-b47c-68588064b4cb", "exec": [ "var response = pm.response.json();", "", @@ -881,10 +841,7 @@ "value": "read", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/case/link/user", @@ -953,10 +910,7 @@ "value": "", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/case/{{case-id}}", @@ -1033,8 +987,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "player", @@ -1045,7 +998,6 @@ { "listen": "test", "script": { - "id": "6a4896f8-c94a-4be5-b72e-6a37db0822c9", "exec": [ "" ], @@ -1075,7 +1027,6 @@ { "listen": "test", "script": { - "id": "e4d4a6d3-357b-4d04-aa09-2d744abe950e", "exec": [ "" ], @@ -1097,10 +1048,7 @@ "value": "ea8dbc12-e879-46e6-b5d7-e67ad88e841b", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/player/quest/cases", @@ -1116,8 +1064,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "author", @@ -1128,7 +1075,6 @@ { "listen": "test", "script": { - "id": "1fca660b-8774-4143-814c-db7afee7efd3", "exec": [ "" ], @@ -1158,7 +1104,6 @@ { "listen": "test", "script": { - "id": "d71fe530-8ff2-4d64-8793-5d77ceaf5ccb", "exec": [ "" ], @@ -1180,10 +1125,7 @@ "value": "5131b64a-04ff-4aec-af98-0edab334fd02", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/author/quest/cases", @@ -1199,8 +1141,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "artifact", @@ -1242,10 +1183,7 @@ "value": "desafio-pocus-image", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/artifact", @@ -1282,7 +1220,6 @@ { "listen": "prerequest", "script": { - "id": "7bc7d2a4-7bbc-48af-8fee-153860cad3d5", "type": "text/javascript", "exec": [ "" @@ -1292,15 +1229,13 @@ { "listen": "test", "script": { - "id": "d36a0f4e-2db8-434c-b0bc-770d22e17c89", "type": "text/javascript", "exec": [ "" ] } } - ], - "protocolProfileBehavior": {} + ] }, { "name": "quest", @@ -1311,7 +1246,6 @@ { "listen": "test", "script": { - "id": "69612a32-fec9-4c59-b25d-2b672a45cbf1", "exec": [ "" ], @@ -1333,10 +1267,7 @@ "value": "5885fb0d-ce64-421f-9b9e-1ea2cef3143f", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/quest/users", @@ -1357,7 +1288,6 @@ { "listen": "test", "script": { - "id": "eb43d5c2-763e-4c25-ac0a-0b2ddf2179cb", "exec": [ "var response = pm.response.json();", "", @@ -1395,10 +1325,7 @@ "value": "f9679a24-58f3-4741-9752-f40d0b4f4ab0", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/quest/", @@ -1436,10 +1363,7 @@ "value": "player", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/quest/link/user", @@ -1478,10 +1402,7 @@ "value": "0", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/quest/link/case", @@ -1497,8 +1418,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "category", @@ -1509,7 +1429,6 @@ { "listen": "test", "script": { - "id": "626a67ae-8150-4f96-bc9f-2f7c16c9bde9", "exec": [ "" ], @@ -1528,12 +1447,12 @@ "formdata": [ { "key": "categoryId", - "value": "quiz-da-emergencia", + "value": "decisoes-extremas", "type": "text" }, { "key": "clearance", - "value": "4", + "value": "1", "type": "text" }, { @@ -1545,18 +1464,21 @@ { "key": "fInstitution", "value": "c5562bfd-9a94-40f0-b08a-3627e3e417e0", - "type": "text" + "type": "text", + "disabled": true }, { "key": "fUserType", "value": "aluno", "type": "text", "disabled": true + }, + { + "key": "fSpecialty", + "value": "especialidade 1", + "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/category/cases", @@ -1577,7 +1499,6 @@ { "listen": "test", "script": { - "id": "3b6e6f6b-df17-42e8-959a-513e0dedc099", "exec": [ "var response = pm.response.json();", "", @@ -1620,10 +1541,7 @@ "value": "desafio-pocus-image", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/category/", @@ -1661,10 +1579,7 @@ "value": "0", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/category/link/case", @@ -1733,8 +1648,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "institution", @@ -1756,8 +1670,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] }, { "name": "admin", @@ -1768,7 +1681,6 @@ { "listen": "test", "script": { - "id": "0da4e91e-5a5a-43c6-8fef-223dce72f31f", "exec": [ "var response = pm.response.json();", "", @@ -1792,10 +1704,7 @@ "header": [], "body": { "mode": "formdata", - "formdata": [], - "options": { - "formdata": {} - } + "formdata": [] }, "url": { "raw": "{{api-base-url}}/admin/cases", @@ -1816,7 +1725,6 @@ { "listen": "test", "script": { - "id": "edfe7693-8604-45bf-b2bf-600cea846dc0", "exec": [ "var response = pm.response.json();", "", @@ -1849,10 +1757,7 @@ "header": [], "body": { "mode": "formdata", - "formdata": [], - "options": { - "formdata": {} - } + "formdata": [] }, "url": { "raw": "{{api-base-url}}/admin/users", @@ -1873,7 +1778,6 @@ { "listen": "test", "script": { - "id": "540ef4ca-e4a5-499d-b06b-e538b4702286", "exec": [ "" ], @@ -1903,7 +1807,6 @@ { "listen": "test", "script": { - "id": "6055d49e-f43b-4c6e-8a1f-b63e32c17e11", "exec": [ "" ], @@ -1935,7 +1838,6 @@ { "listen": "test", "script": { - "id": "222550fd-5a12-4a17-bcef-a3ae88e1be3f", "exec": [ "" ], @@ -1977,10 +1879,7 @@ "value": "41353296-c9ac-4365-83b6-4c9dbc845930", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/admin/user/link/role", @@ -2003,7 +1902,6 @@ { "listen": "test", "script": { - "id": "29920f59-a6b7-4f3e-8909-b7171419cb07", "exec": [ "" ], @@ -2039,10 +1937,7 @@ "value": "BR", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/admin/institution", @@ -2063,7 +1958,6 @@ { "listen": "test", "script": { - "id": "519ed505-fbc6-4eb8-995e-c704486a84b7", "exec": [ "" ], @@ -2083,10 +1977,7 @@ ], "body": { "mode": "formdata", - "formdata": [], - "options": { - "formdata": {} - } + "formdata": [] }, "url": { "raw": "{{api-base-url}}/admin/revoke_tokens", @@ -2124,10 +2015,7 @@ "value": "author", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/admin/quest/link/user", @@ -2150,7 +2038,6 @@ { "listen": "test", "script": { - "id": "f1647ef8-7e68-4b0a-8bfe-91b84283904f", "exec": [ "" ], @@ -2186,10 +2073,7 @@ "value": "Research project member", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/admin/role", @@ -2282,8 +2166,7 @@ "response": [] } ], - "description": "Services for administrate `harena`", - "protocolProfileBehavior": {} + "description": "Services for administrate `harena`" }, { "name": "group", @@ -2294,7 +2177,6 @@ { "listen": "test", "script": { - "id": "94c53d16-ddb2-40c4-8c24-9849f2caf53c", "exec": [ "" ], @@ -2316,10 +2198,7 @@ "value": "37b4159f-b2bf-4014-b5dc-655df6506311", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/group/cases", @@ -2340,7 +2219,6 @@ { "listen": "test", "script": { - "id": "7667499e-a7f5-4236-9eb6-3e8ca72e7e27", "exec": [ "var response = pm.response.json();", "", @@ -2368,10 +2246,7 @@ "value": "Turma do Minho", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/group/", @@ -2404,10 +2279,7 @@ "value": "781c4351-16d7-4b24-b214-bb9fdb3e75bf", "type": "text" } - ], - "options": { - "formdata": {} - } + ] }, "url": { "raw": "{{api-base-url}}/group/link/user", @@ -2423,8 +2295,7 @@ }, "response": [] } - ], - "protocolProfileBehavior": {} + ] } ], "auth": { @@ -2441,7 +2312,6 @@ { "listen": "prerequest", "script": { - "id": "304b8626-14c1-4881-8a2a-881c9fa0d3bc", "type": "text/javascript", "exec": [ "" @@ -2451,13 +2321,11 @@ { "listen": "test", "script": { - "id": "67ec55a1-a62c-4dc7-bcfe-0d21b1d13da8", "type": "text/javascript", "exec": [ "" ] } } - ], - "protocolProfileBehavior": {} + ] } \ No newline at end of file From 29136aa5dd54749f14e7188525745431eac85442 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Wed, 3 Feb 2021 15:36:27 -0300 Subject: [PATCH 10/15] fix (controller/category): change restriction endpoints --- src/adonisjs/app/Controllers/Http/v1/AuthController.js | 4 +++- src/adonisjs/start/routes.js | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/AuthController.js b/src/adonisjs/app/Controllers/Http/v1/AuthController.js index 3aa8655..ad4abb3 100644 --- a/src/adonisjs/app/Controllers/Http/v1/AuthController.js +++ b/src/adonisjs/app/Controllers/Http/v1/AuthController.js @@ -3,13 +3,15 @@ const Logger = use('Logger') const User = use('App/Models/v1/User') +const Institution = use('App/Models/v1/Institution') class AuthController { async checkToken ({ request, auth, response }) { try { // console.log('====Checking token...') if(await auth.check()){ - response.json({token:'token valid', username: auth.user.username}) + let userInstitution = await Institution.findBy('id', auth.user.institution_id) + response.json({token:'token valid', username: auth.user.username, grade: auth.user.grade, institution: userInstitution.acronym}) } // console.log('====Token valid') } catch (error) { diff --git a/src/adonisjs/start/routes.js b/src/adonisjs/start/routes.js index 656d7e8..46361f4 100644 --- a/src/adonisjs/start/routes.js +++ b/src/adonisjs/start/routes.js @@ -135,12 +135,16 @@ Route.group(() => { Route.group(() => { Route.post( '', 'v1/CategoryController.store') Route.post( 'link/case', 'v1/CategoryController.linkCase') - Route.get( 'list', 'v1/CategoryController.listCategories') - Route.get( 'cases', 'v1/CategoryController.listCases') Route.put( ':id', 'v1/CategoryController.update') }).prefix('/api/v1/category').middleware('auth', 'is:author') +Route.group(() => { + Route.get( 'list', 'v1/CategoryController.listCategories') + Route.get( 'cases', 'v1/CategoryController.listCases') + +}).prefix('/api/v1/category').middleware('auth') + /* |---------------------------------------------------------------------------------------------- | api: v1 From 84640cde55bb8506e661e63bf7e928dcf45997cf Mon Sep 17 00:00:00 2001 From: Fagner Date: Wed, 3 Feb 2021 21:38:58 -0300 Subject: [PATCH 11/15] feat (database): add column subject_grade into table permissions --- ...ager_-_production.postman_environment.json | 94 +++++++++++++++++++ ...86445_update_case_drop_course_id_schema.js | 21 +++++ ...te_permissions_add_subject_grade_schema.js | 20 ++++ 3 files changed, 135 insertions(+) create mode 100644 harena-manager_-_production.postman_environment.json create mode 100644 src/adonisjs/database/migrations/1612398386445_update_case_drop_course_id_schema.js create mode 100644 src/adonisjs/database/migrations/1612398605359_update_permissions_add_subject_grade_schema.js diff --git a/harena-manager_-_production.postman_environment.json b/harena-manager_-_production.postman_environment.json new file mode 100644 index 0000000..8e8b984 --- /dev/null +++ b/harena-manager_-_production.postman_environment.json @@ -0,0 +1,94 @@ +{ + "id": "5d02c2ab-c7ad-460e-bb7f-ab67b89808e2", + "name": "harena-manager - production", + "values": [ + { + "key": "protocol", + "value": "https://", + "enabled": true + }, + { + "key": "host", + "value": "harena.ds4h.org", + "enabled": true + }, + { + "key": "port", + "value": "443", + "enabled": true + }, + { + "key": "api-version", + "value": "v1", + "enabled": true + }, + { + "key": "api-base-url", + "value": "{{protocol}}{{host}}/manager/api/{{api-version}}", + "enabled": true + }, + { + "key": "user-id", + "value": 130, + "enabled": true + }, + { + "key": "user-email", + "value": "jacinto@email.com", + "enabled": true + }, + { + "key": "user-username", + "value": "jacinto", + "enabled": true + }, + { + "key": "user-password", + "value": "jacinto", + "enabled": true + }, + { + "key": "user-token", + "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTU4Mzk2ODUzMn0.FWwj3i0VFKOJakMM_1Oo6Ads0gkMYYjcmcqkE4UjbrA", + "enabled": true + }, + { + "key": "case-uuid", + "value": "d5d804b0-1876-4430-a5bf-42b442eeb26a", + "enabled": true + }, + { + "key": "case-name", + "value": "case001-development", + "enabled": true + }, + { + "key": "case-source", + "value": "Start\n=====\n\n## Case 001 (start,dialog_left)\n:NURSE Agnes: Doctor, we have a man (51 years old) who entered the emergency department reporting chest pain. His vital signs are ABP: 144x92mmHG; HR: 78bpm; RR: 21rpm; Temp: 37oC; O2Sat: 98%.\n\n* Let us go! -> Cycle 1.Begin\n\nCycle 1\n=======\n\nBegin (information)\n-------------------\n\n:PATIENT Jakob: Doctor, I am feeling chest pain since yesterday. The pain is continuous and is located just in the middle of my chest, worsening when I breathe and when I lay down on my bed. I suffer from arterial hypertension and smoke 20 cigarettes every day. My father had a “heart attack” at my age and I am very worried about it.\n\nPHYSICAL EXAMINATION
The cardiac and pulmonary auscultation are normal; chest pain does not worse with palpation of the thorax; there is no jugular stasis nor lower limb edema.\n\n:Jacinto:What do you want to do?\n\n* -> Generate hypothesis\n* -> More information\n* Call the supervisor -> Call the supervisor.A\n\nGenerate hypothesis (input)\n---------------------------\nWhat is your main diagnostic hypothesis?\n:PATIENT Jakob:.\n{?1 hypothesis:mesh#pericarditis,myopericarditis,pericardial inflammation,pericardial infection,pericardial effusion;infarction,myocardial infarction,coronary syndrome,acute coronary syndrome,ischemia,myocardial ischemia,coronary insufficiency,angina,angina pectoris}\n\n* Submit hypothesis -> Check hypothesis\n\nMore information (information)\n------------------------------\n\nMORE INFORMATION
The patient never felt chest pain before. He exercises regularly and has lost weight in the last three months. He takes amlodipine and losartan regularly. Two weeks ago, he had an auto-limited gastroenteritis episode. He denies recent travels and surgery.\n:PATIENT Jakob:.\n\n:Jacinto:What do you want to do?\n\n* Back to the case -> Cycle 1.Begin\n\nCall the supervisor\n-------------------\n\n### A (detailed)\n:SUPERVISOR Harry:\nHi! I am glad that you called me. Chest pain is an important complaint at the emergency department and we have to exclude the fatal causes: myocardial infarction (MI), acute aortic dissection (AAD), pulmonary embolism PE), hypertensive pneumothorax (HP), and Boerhaave Syndrome (BS).\n\nThe best way to find out what is happening with your patient, my young padawan, is to gather as much information as possible through history taking and physical examination. We need to search for the signs and symptoms that can guide our clinical reasoning process by changing the pre-test probabilities of each disease.\n::\n\n* See likelihood tables -> B \n\n### B (detailed)\n:SUPERVISOR Harry:.\n**Likelihood Tables**\n\nDo you know the concept of Likelihood ratio (LR)? -> Likelihood Ratio\n\n+ -> Clinical History Myocardial Infarction\n\n+ -> Physical Examination Myocardial Infarction\n\n+ -> Clinical History Aortic Dissection\n\n+ -> Physical Examination Aortic Dissection\n\n+ -> Pulmonary Embolism Wells Criteria\n\n* Continue talking -> C \n\n### C (detailed)\n:SUPERVISOR Harry:.\nHypertensive pneumothorax is more common in tall and thin young adults (primary pneumothorax) or in patients with chronic pulmonary diseases or chest trauma (secondary pneumothorax). On physical examination, we expect asymmetry in lung auscultation and the trachea may be dislocated to the contralateral side of the pneumothorax.\n\nBoerhaave Syndrome is more common in patients who presented vomiting before the chest pain started, were submitted to endoscopic procedures or had chest trauma.\n\nHow does this information can help you to solve your case?\n\n* Back to the case -> Cycle 1.Begin\n\n### Likelihood Ratio (note)\n\nLikelihood ratio (LR) - like sensitivity and specificity, LR describe the discriminatory power of features in a clinical context, estimating the probability of disease. When the LR is higher than 1, the feature increases the probability; when lower than 1, reduces it.\n\n* Back -> Supervisor B\n\n### Clinical History Myocardial Infarction (note)\n![Clinical History Myocardial Infarction](images/ebm-clinical-history-myocardial-infarction.png)\n\n* Back -> Supervisor B\n\n### Physical Examination Myocardial Infarction (note)\n![Physical Examination Myocardial Infarction](images/ebm-physical-examination-myocardial-infarction.png)\n\n* Back -> Supervisor B\n\n### Clinical History Aortic Dissection (note)\n![Clinical History Aortic Dissection](images/ebm-clinical-history-aortic-dissection.png)\n\n* Back -> Supervisor B\n\n### Physical Examination Aortic Dissection (note)\n![Physical Examination Aortic Dissection](images/ebm-physical-examination-aortic-dissection.png)\n\n* Back -> Call the supervisor B\n\n### Pulmonary Embolism Wells Criteria (note)\n![Pulmonary Embolism Wells Criteria](images/ebm-pulmonary-embolism-wells-criteria.png)\n\n* Back -> Call the supervisor B\n\nCheck hypothesis (selector)\n---------------------------\n\n:Jacinto:Let us check out your hypothesis. Highlight in green the findings that corroborate your hypothesis; in blue those that are neutral; and in red the ones speaking against your hypothesis.\n\n{{symptoms#contribution to diagnostics: ,+,=,-\nNurse: Doctor, please you have to evaluate a {man(male)} ({51 years-old(aging=51)#=}) who entered the emergency department reporting {chest pain#=}.His vital signs are {ABP: 144x92mmHG#=}; {HR: 78bpm#=}; {RR: 21rpm#=}; {Temp: 37oC#=}; {O2Sat: 98%#=}.\n\nPatient: Doctor, I am feeling chest pain since yesterday. The {pain is continuous#=} and {is located just in the middle of my chest#=}, {worsening when I breathe#+} and {when I lay down on my bed#+}. I have {arterial hypertension#-} and {I smoke 20 cigarettes(smoking=20/day)#-} every day. {My father had a \"heart attack\"#-} at my age and I am very worried about it.\n\nYou perform physical examination: {cardiac and pulmonary auscultation are normal#-}; {chest pain does not worse with palpation of the thorax#=}; {there is no jugular stasis#=} {nor lower limb edema#=}.\n}}\n\n* Submit -> Review hypothesis \n\nReview hypothesis (input)\n-------------------------\nIf you whant to review your hypothesis, type below the new hypothesis.\n:PATIENT Jakob:.\n{?1 hypothesis:mesh#pericarditis,myopericarditis,pericardial inflammation,pericardial infection,pericardial effusion;infarction,myocardial infarction,coronary syndrome,acute coronary syndrome,ischemia,myocardial ischemia,coronary insufficiency,angina,angina pectoris}\n\n* Submit -> Cycle 2.Order EKG\n\nCycle 2\n=======\n\n## Order EKG (decision_exam)\nOur patient denies any recent long trip, immobilization or surgery.\n\nThe blood pressure is symmetric in the four limbs. \n\n:EKG:.\n\n* Magnify -> Magnify EKG\n\n:Game: What do you want to do?\n* -> Generate hypothesis\n* -> More information\n* -> Call the supervisor\n\n\n## Magnify EKG (note,magnify_exam)\n\n:EKG:.\n\n* Return -> Order EKG\n\n## Generate hypothesis (input)\nWhat is your main diagnostic hypothesis?\n:PATIENT Jakob:.\n{?1 hypothesis:mesh#pericarditis,myopericarditis,pericardial inflammation,pericardial infection,pericardial effusion;infarction,myocardial infarction,coronary syndrome,acute coronary syndrome,ischemia,myocardial ischemia,coronary insufficiency,angina,angina pectoris}\n\n* Submit hypothesis -> Check hypothesis\n\n## More information (decision_exam)\n\n![EKG Description](images/ekg-description.png)\n\n* EKG Analysis\n\n:EKG:.\n\n:Game: What do you want to do?\n* Back -> Order EKG\n* Analyze EKG -> EKG Analysis\n\n## EKG Analysis (note,marker_exam)\n\n\n \n \n \n \n \n \n \n\n\n* Return -> Order EKG\n\n## Call the supervisor (decision_exam)\n\nWe did not find features that increase the likelihood of myocardial ischemia. Moreover, our patient has a pleuritic chest pain that gets worse when the patient lays down.\n\nIn the EKG we found ST-segment elevation in almost all leads. Also, we found a depression of the PR segment in the DII lead.\n\n* -> EKG Analysis\n\n:EKG:.\n\n:Game: What do you want to do?\n* Back -> Order EKG\n* Analyze EKG -> EKG Analysis\n\n## Check hypothesis (marker_exam)\n\n\n \n \n \n \n \n \n \n\n\n* Submit -> Review hypothesis\n\n## Review hypothesis (input)\nIf you whant to review your hypothesis, type below the new hypothesis.\n:PATIENT Jakob:.\n{?1 hypothesis:mesh#pericarditis,myopericarditis,pericardial inflammation,pericardial infection,pericardial effusion;infarction,myocardial infarction,coronary syndrome,acute coronary syndrome,ischemia,myocardial ischemia,coronary insufficiency,angina,angina pectoris}\n\n* Submit -> Final.Report\n\nFinal\n=====\n\nReport (detailed)\n-----------------\n\nCongratulations, my young Dr. you could helped your patient providing his diagnosis. Now, Let's review all levels of this case.\n\n:Computer:Select a final report level:\n\n* -> Level 1\n* -> Level 2.2a\n* -> Level 3.3a\n\nLevel 1 (detailed)\n------------------\n\nLevel 1: your answer was .\n\nOur patient complained about chest pain, located in the middle of his chest, worsening when he breaths and when he lay down on his bed. Both features increases the probability of pericardial disease, especially acute pericarditis. Although patient´s father died of a \"heart attack\", there were no chest pain features that increase the probability of myocardial infarction, as the pain did not irradiate to arms, the pain was not described as a pressure, neither complaining about nausea, vomiting or shortness of breath. Another differential diagnosis to consider is myopericarditis, but we not be able to find heart failure signs (pulmonary and cardiac auscultation were normal) and the patient did not complain about dyspnea. So, at the level 1, the answer to our open-ended question was Acute Pericarditis.\n\n* Next -> Level 2.2a\n* Return -> Report\n\nLevel 2\n-------\n\n### 2a (detailed)\n\n
\nLevel 2: At this level, we asked you to highlight in green all features that corroborate your hypothesis, in blue those are neutral and in red the ones speaking against your hypothesis.\n

\nYour answer:\n
\n{{player#Cycle_1.Check_hypothesis.symptoms: ,+,=,-\nNurse: Doctor, please you have to evaluate a {man(male)} ({51 years-old(aging=51)#=}) who entered the emergency department reporting {chest pain#=}.His vital signs are {ABP: 144x92mmHG#=}; {HR: 78bpm#=}; {RR: 21rpm#=}; {Temp: 37oC#=}; {O2Sat: 98%#=}.\n
\nPatient: Doctor, I am feeling chest pain since yesterday. The {pain is continuous#=} and {is located just in the middle of my chest#=}, {worsening when I breathe#+} and {when I lay down on my bed#+}. I have {arterial hypertension#-} and {I smoke 20 cigarettes(smoking=20/day)#-} every day. {My father had a \"heart attack\"#-} at my age and I am very worried about it.\n
\nYou perform physical examination: {cardiac and pulmonary auscultation are normal#-}; {chest pain does not worse with palpation of the thorax#=}; {there is no jugular stasis#=} {nor lower limb edema#=}.\n}}\n

\nOur answer: \n
\n{{answers#answers: ,+,=,-\nNurse: Doctor, please you have to evaluate a {man(male)} ({51 years-old(aging=51)#=}) who entered the emergency department reporting {chest pain#=}.His vital signs are {ABP: 144x92mmHG#=}; {HR: 78bpm#=}; {RR: 21rpm#=}; {Temp: 37oC#=}; {O2Sat: 98%#=}.\n
\nPatient: Doctor, I am feeling chest pain since yesterday. The {pain is continuous#=} and {is located just in the middle of my chest#=}, {worsening when I breathe#+} and {when I lay down on my bed#+}. I have {arterial hypertension#-} and {I smoke 20 cigarettes(smoking=20/day)#-} every day. {My father had a \"heart attack\"#-} at my age and I am very worried about it.\n
\nYou perform physical examination: {cardiac and pulmonary auscultation are normal#-}; {chest pain does not worse with palpation of the thorax#=}; {there is no jugular stasis#=} {nor lower limb edema#=}.\n}}\n
\n\n* Next -> 2b\n* Return -> Final.Report\n\n### 2b (detailed)\n\nAfter checking the hypothesis you reviewed your answer to: .\n\nIn acute pericarditis, patients are usually young, most cases are reported under 50 years old, but it can be diagnosed at any age. There is no vital signs features that increase the probability of this condition. Some patients may present fever and tachycardia, but it´s not common signs. So, when vital signs are normal, we cannot confirm or exclude this diagnosis.\n\nIn clinical history, two features increase the probability of the chest pain being related to a pericardial disease: worsening with breathing; and worsening when the patient lay down. \n\n* Next -> 2c\n* Return -> Final.Report\n\n### 2c (detailed)\n\nAs the patient has arterial hypertension, is smoker and his father died of a \"heart attack\" we could consider myocardial infarction as one of the diagnosis. But considering chest pain features of our patient, there is no one that increases this possibility. So, these features may lead us to cognitive error if we consider myocardial infarction as the main diagnosis (which is wrong). \n\nIn physical examination in patients with acute pericarditis, we may find pericardial rub, one of the diagnostic criteria. So, when we did not find it, the probability of the disease is reduced, but did not exclude the diagnosis. It is crucial to look for the other diagnostic criteria.\n\n* Next -> Level 3.3a\n* Return -> Final.Report\n\nLevel 3\n-------\n\n### 3a (detailed)\n\nMy young Dr, the EKG interpretation was very helpful to solve our case.\n\nWe found a diffuse ST-segment elevation, and a PR-segment depression in DII lead. These findings, associated to the clinical scenario, strongly indicate the main hypothesis of Acute Pericarditis.\n\n* Next -> 3b\n* Return -> Final.Report\n\n### 3b (detailed)\n\nMy young Dr, the EKG interpretation was very helpful to solve our case.\n\nWe found a diffuse ST-segment elevation, and a PR-segment depression in DII lead. These findings, associated to the clinical scenario, strongly indicate the main hypothesis of Acute Pericarditis.\n\n* Next -> 3c\n* Return -> Final.Report\n\n### 3c (detailed)\n
\nIn the following table, we provide the diagnostic criteria for acute pericaditis and myopericarditis:\n\n![Clinical History Myocardial Infarction](images/ebm-pericarditis.png)\n\nCooper LT, Imazio M. Management of myopericarditis. Expert Rev Cardiovasc Ther 2013; 11(2): 193-201.\n\nOur patient fullfill the following criteria: 1 and 3. So, acute pericarditis is the main diagnostic hypothesis.\n
\n\n* Return -> Final.Report \n", + "enabled": true + }, + { + "key": "filterBy-user", + "value": "user", + "enabled": true + }, + { + "key": "case-id", + "value": "", + "enabled": true + }, + { + "key": "user-refreshToken", + "value": "", + "enabled": true + }, + { + "key": "quest-id", + "value": "", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2020-10-25T22:36:50.123Z", + "_postman_exported_using": "Postman/7.34.0" +} \ No newline at end of file diff --git a/src/adonisjs/database/migrations/1612398386445_update_case_drop_course_id_schema.js b/src/adonisjs/database/migrations/1612398386445_update_case_drop_course_id_schema.js new file mode 100644 index 0000000..05dc820 --- /dev/null +++ b/src/adonisjs/database/migrations/1612398386445_update_case_drop_course_id_schema.js @@ -0,0 +1,21 @@ +'use strict' + +/** @type {import('@adonisjs/lucid/src/Schema')} */ +const Schema = use('Schema') + +class UpdateCaseDropCourseIdSchema extends Schema { + up () { + this.table('users', (table) => { + table.dropForeign('course_id') + table.dropColumn('course_id') + }) + } + + down () { + this.table('users', (table) => { + table.uuid('course_id').references('id').inTable('courses').index('course_id') + }) + } +} + +module.exports = UpdateCaseDropCourseIdSchema diff --git a/src/adonisjs/database/migrations/1612398605359_update_permissions_add_subject_grade_schema.js b/src/adonisjs/database/migrations/1612398605359_update_permissions_add_subject_grade_schema.js new file mode 100644 index 0000000..14326b6 --- /dev/null +++ b/src/adonisjs/database/migrations/1612398605359_update_permissions_add_subject_grade_schema.js @@ -0,0 +1,20 @@ +'use strict' + +/** @type {import('@adonisjs/lucid/src/Schema')} */ +const Schema = use('Schema') + +class UpdatePermissionsAddSubjectGradeSchema extends Schema { + up () { + this.table('permissions', (table) => { + table.string('subject_grade', 20) + }) + } + + down () { + this.table('permissions', (table) => { + table.dropColumn('subject_grade') + }) + } +} + +module.exports = UpdatePermissionsAddSubjectGradeSchema From 1792988790087f001d96c69aa7da1f39b29e82c3 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Sun, 7 Feb 2021 02:52:41 -0300 Subject: [PATCH 12/15] feat (case/property): new endpoints and route change --- .../app/Controllers/Http/v1/AuthController.js | 3 +- .../app/Controllers/Http/v1/CaseController.js | 131 +++++++++++++++++- .../Controllers/Http/v1/CategoryController.js | 7 +- .../app/Controllers/Http/v1/UserController.js | 9 +- .../app/Middleware/CheckCasePermission.js | 15 ++ src/adonisjs/app/Models/v1/CaseProperty.js | 15 ++ src/adonisjs/app/Models/{ => v1}/Property.js | 0 src/adonisjs/start/routes.js | 9 +- 8 files changed, 175 insertions(+), 14 deletions(-) create mode 100644 src/adonisjs/app/Models/v1/CaseProperty.js rename src/adonisjs/app/Models/{ => v1}/Property.js (100%) diff --git a/src/adonisjs/app/Controllers/Http/v1/AuthController.js b/src/adonisjs/app/Controllers/Http/v1/AuthController.js index ad4abb3..4b7882e 100644 --- a/src/adonisjs/app/Controllers/Http/v1/AuthController.js +++ b/src/adonisjs/app/Controllers/Http/v1/AuthController.js @@ -11,7 +11,8 @@ class AuthController { // console.log('====Checking token...') if(await auth.check()){ let userInstitution = await Institution.findBy('id', auth.user.institution_id) - response.json({token:'token valid', username: auth.user.username, grade: auth.user.grade, institution: userInstitution.acronym}) + response.json({token:'token valid', username: auth.user.username, + grade: auth.user.grade, institution: userInstitution.acronym, institutionId: auth.user.institution_id}) } // console.log('====Token valid') } catch (error) { diff --git a/src/adonisjs/app/Controllers/Http/v1/CaseController.js b/src/adonisjs/app/Controllers/Http/v1/CaseController.js index 00eb769..18adbf9 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CaseController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CaseController.js @@ -11,6 +11,8 @@ const Case = use('App/Models/v1/Case') const CaseVersion = use('App/Models/v1/CaseVersion') const Institution = use('App/Models/v1/Institution') const Permission = use('App/Models/v1/Permission') +const Property = use('App/Models/v1/Property') +const CaseProperty = use('App/Models/v1/CaseProperty') const uuidv4 = require('uuid/v4') @@ -36,18 +38,33 @@ class CaseController { * @param {Response} ctx.response * @param {View} ctx.view */ - async show ({ params, response }) { + async show ({ request, response }) { try { - const c = await Case.find(params.id) + + const c = await Case.find(request.input('caseId')) if (c != null) { const versions = await CaseVersion.query() - .where('case_id', '=', params.id) + .where('case_id', '=', request.input('caseId')) .orderBy('created_at', 'asc') .fetch() + const properties = await Database + .select(['properties.title', 'case_properties.value']) + .from('case_properties') + .leftJoin('properties', 'case_properties.property_id', 'properties.id') + .where('case_properties.case_id', request.input('caseId')) + + var prop = {} + for(let p in properties){ + let title = properties[p].title + let value = properties[p].value + prop[title] = value + } + c.source = versions.last().source c.versions = versions + c.property = prop const institution = await Institution.find(c.institution_id) c.institution = institution.acronym @@ -112,11 +129,11 @@ class CaseController { } /** * Update case details. PUT or PATCH case/:id */ - async update ({ params, request, response }) { + async update ({ request, response }) { const trx = await Database.beginTransaction() try { - const c = await Case.find(params.id) + const c = await Case.find(request.input('caseId')) if (c != null) { c.title = request.input('title') || null @@ -171,10 +188,10 @@ class CaseController { * @param {Request} ctx.request * @param {Response} ctx.response */ - async destroy ({ params, response }) { + async destroy ({ request, response }) { const trx = await Database.beginTransaction() try { - const c = await Case.findBy('id', params.id) + const c = await Case.findBy('id', request.input('caseId')) if (c != null) { await c.versions().delete() @@ -204,6 +221,7 @@ class CaseController { try { const entity = request.input('entity') const subject = request.input('subject') + const subject_grade = request.input('subject_grade') const clearance = request.input('clearance') const table_id = request.input('table_id').split(',') // console.log(entity) @@ -221,6 +239,7 @@ class CaseController { permission.id = await uuidv4() permission.entity = entity permission.subject = subject + permission.subject_grade = subject_grade permission.clearance = clearance permission.table = 'cases' permission.table_id = table_id[c] @@ -238,6 +257,104 @@ class CaseController { } + async storeProperty ({params, request, auth, response}) { + const trx = await Database.beginTransaction() + try { + const case_id = request.input('case_id') + const property_title = request.input('property_title') + const property_value = request.input('property_value') + + const property = await Property.findOrCreate( + { title: property_title }, + { id: await uuidv4(), title: property_title }, trx + ) + // const caseProperty = new CaseProperty() + // caseProperty.case_id = case_id + // caseProperty.property_id = property.id + // caseProperty.value = property_value + let caseProperty = await CaseProperty.findOrCreate( + { case_id: case_id, property_id: property.id}, + { case_id: case_id, property_id: property.id, value: property_value}, trx + ) + caseProperty.value = property_value + + await property.save(trx) + console.log('============ passei do property') + await caseProperty.save(trx) + console.log('============ passei do case property') + + trx.commit() + + return response.json({property: property, case_property: caseProperty}) + + } catch (e) { + trx.rollback() + console.log('============catch diiiiis') + console.log(e) + return response.status(e.status).json({ message: e.message}) + } + } + + async updateProperty ({request, auth, response}) { + const trx = await Database.beginTransaction() + try { + const case_id = request.input('case_id') + const property_title = request.input('property_title') + const property_value = request.input('property_value') + console.log('============ case id') + console.log(case_id) + console.log('============ title prop') + console.log(property_title) + console.log('============ value prop') + console.log(property_value) + + const property = await Property.findBy('title', property_title) + + // const caseProperty = await CaseProperty.findOrCreate( + // { case_id: case_id, property_id: property.id }, + // { case_id: case_id, property_id: property.id}, trx + // ) + + let caseProperty = await CaseProperty + .query() + .where('property_id', property.id) + .where('case_id', case_id) + .fetch() + caseProperty = caseProperty.last() + + await Database + .table('case_properties') + .where('property_id', property.id) + .where('case_id', case_id) + .update({ value: property_value,}) + console.log('============ db case property') + + console.log(caseProperty) + + caseProperty.value = property_value + + console.log('============ value') + console.log(caseProperty.value) + + + + return response.json(caseProperty) + } catch (e) { + + console.log('============catch diiiiis') + console.log(e) + return response.status(e.status).json({ message: e.message }) + } + } + + async deleteProperty ({params, request, auth, response}) { + try { + + } catch (e) { + return response.status(e.status).json({ message: e.message }) + } + } + } module.exports = CaseController diff --git a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js index 233f8da..3686048 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CategoryController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CategoryController.js @@ -108,7 +108,7 @@ class CategoryController { if (specialtyFilter != '%') this.where('cases.specialty', 'like', specialtyFilter) }) - + .where(function(){ this .where('cases.author_id', user.id) @@ -117,6 +117,11 @@ class CategoryController { .where('permissions.entity', 'institution') .where('permissions.subject', user.institution_id) .where('permissions.clearance', '>=', clearance) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', user.grade) + }) }) }) .orderBy('cases.created_at', 'desc') diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index 13e2919..348a9e6 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -13,7 +13,7 @@ const User = use('App/Models/v1/User') const Institution = use('App/Models/v1/Institution') const Artifact = use('App/Models/v1/Artifact') const Quest = use('App/Models/v1/Quest') -const Property = use('App/Models/Property') +const Property = use('App/Models/v1/Property') const uuidv4 = require('uuid/v4') const Env = use('Env') @@ -224,7 +224,7 @@ class UserController { if (specialtyFilter != '%') this.where('cases.specialty', 'like', specialtyFilter) }) - + .where(function(){ this .where('cases.author_id', user.id) @@ -233,6 +233,11 @@ class UserController { .where('permissions.entity', 'institution') .where('permissions.subject', user.institution_id) .where('permissions.clearance', '>=', clearance) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', user.grade) + }) }) }) .orderBy('cases.created_at', 'desc') diff --git a/src/adonisjs/app/Middleware/CheckCasePermission.js b/src/adonisjs/app/Middleware/CheckCasePermission.js index 5dd980b..5b670a8 100644 --- a/src/adonisjs/app/Middleware/CheckCasePermission.js +++ b/src/adonisjs/app/Middleware/CheckCasePermission.js @@ -36,6 +36,11 @@ class CheckPermissionForGivenCase { .where('permissions.entity', 'institution') .where('permissions.subject', auth.user.institution_id) .where('permissions.clearance', '>=', 1) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', auth.user.grade) + }) }) .count() } @@ -51,6 +56,11 @@ class CheckPermissionForGivenCase { .where('permissions.entity', 'institution') .where('permissions.subject', auth.user.institution_id) .where('permissions.clearance', '>=', 2) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', auth.user.grade) + }) }) .count() } @@ -66,6 +76,11 @@ class CheckPermissionForGivenCase { .where('permissions.entity', 'institution') .where('permissions.subject', auth.user.institution_id) .where('permissions.clearance', '>=', 4) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', auth.user.grade) + }) }) .count() } diff --git a/src/adonisjs/app/Models/v1/CaseProperty.js b/src/adonisjs/app/Models/v1/CaseProperty.js new file mode 100644 index 0000000..a95252f --- /dev/null +++ b/src/adonisjs/app/Models/v1/CaseProperty.js @@ -0,0 +1,15 @@ +'use strict' + +/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ +const Model = use('Model') + +class CaseProperty extends Model { + static get incrementing () { + return false + } + static get table () { + return 'case_properties' + } +} + +module.exports = CaseProperty diff --git a/src/adonisjs/app/Models/Property.js b/src/adonisjs/app/Models/v1/Property.js similarity index 100% rename from src/adonisjs/app/Models/Property.js rename to src/adonisjs/app/Models/v1/Property.js diff --git a/src/adonisjs/start/routes.js b/src/adonisjs/start/routes.js index 46361f4..e41166a 100644 --- a/src/adonisjs/start/routes.js +++ b/src/adonisjs/start/routes.js @@ -66,11 +66,14 @@ Route.group(() => { */ Route.group(() => { Route.post( '', 'v1/CaseController.store') - Route.put( ':id', 'v1/CaseController.update').middleware(['case_permission:write']) - Route.delete(':id', 'v1/CaseController.destroy').middleware(['case_permission:delete']) + Route.put( '', 'v1/CaseController.update').middleware(['case_permission:write']) + Route.delete('', 'v1/CaseController.destroy').middleware(['case_permission:delete']) Route.post('share', 'v1/CaseController.share').middleware(['case_permission:share']) + + Route.post('property', 'v1/CaseController.storeProperty').middleware(['auth', 'case_permission:write']) + Route.put('property', 'v1/CaseController.updateProperty').middleware(['auth', 'case_permission:write']) }).prefix('/api/v1/case').middleware(['auth', 'is:author']) -Route.get( '/api/v1/case/:id', 'v1/CaseController.show').middleware(['auth', 'case_permission:read']) +Route.get( '/api/v1/case', 'v1/CaseController.show').middleware(['auth', 'case_permission:read']) /* From c3bf5a34463bbabb44bac6bbd9551f1bc8e63054 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Sun, 7 Feb 2021 16:48:33 -0300 Subject: [PATCH 13/15] feat (UserController/listCases): feedback filter option --- .../app/Controllers/Http/v1/CaseController.js | 28 ++--- .../app/Controllers/Http/v1/UserController.js | 119 ++++++++++++------ 2 files changed, 92 insertions(+), 55 deletions(-) diff --git a/src/adonisjs/app/Controllers/Http/v1/CaseController.js b/src/adonisjs/app/Controllers/Http/v1/CaseController.js index 18adbf9..de02c51 100644 --- a/src/adonisjs/app/Controllers/Http/v1/CaseController.js +++ b/src/adonisjs/app/Controllers/Http/v1/CaseController.js @@ -276,12 +276,9 @@ class CaseController { { case_id: case_id, property_id: property.id}, { case_id: case_id, property_id: property.id, value: property_value}, trx ) - caseProperty.value = property_value await property.save(trx) - console.log('============ passei do property') await caseProperty.save(trx) - console.log('============ passei do case property') trx.commit() @@ -289,7 +286,7 @@ class CaseController { } catch (e) { trx.rollback() - console.log('============catch diiiiis') + console.log('============catch error storeProperty') console.log(e) return response.status(e.status).json({ message: e.message}) } @@ -301,12 +298,6 @@ class CaseController { const case_id = request.input('case_id') const property_title = request.input('property_title') const property_value = request.input('property_value') - console.log('============ case id') - console.log(case_id) - console.log('============ title prop') - console.log(property_title) - console.log('============ value prop') - console.log(property_value) const property = await Property.findBy('title', property_title) @@ -322,26 +313,25 @@ class CaseController { .fetch() caseProperty = caseProperty.last() - await Database + await trx .table('case_properties') .where('property_id', property.id) .where('case_id', case_id) .update({ value: property_value,}) - console.log('============ db case property') - - console.log(caseProperty) + // console.log('============ db case property') + // console.log(caseProperty) caseProperty.value = property_value - console.log('============ value') - console.log(caseProperty.value) - + // console.log('============ value') + // console.log(caseProperty.value) + trx.commit() return response.json(caseProperty) } catch (e) { - - console.log('============catch diiiiis') + trx.rollback() + console.log('============catch error updateProperty') console.log(e) return response.status(e.status).json({ message: e.message }) } diff --git a/src/adonisjs/app/Controllers/Http/v1/UserController.js b/src/adonisjs/app/Controllers/Http/v1/UserController.js index 348a9e6..abd372b 100644 --- a/src/adonisjs/app/Controllers/Http/v1/UserController.js +++ b/src/adonisjs/app/Controllers/Http/v1/UserController.js @@ -193,54 +193,101 @@ class UserController { try { const user = await auth.user - const clearance = parseInt(request.input('clearance')) + const clearance = parseInt(request.input('clearance')) || 10 var publishedFilter = parseInt(request.input('published')) || 0 const institutionFilter = request.input('fInstitution') || `%` const userTypeFilter = request.input('fUserType') || `%` const specialtyFilter = request.input('fSpecialty') || `%` - // console.log('============') + const propertyFilter = request.input('fProperty') || null + const propertyValueFilter = request.input('fPropertyValue') || '%' + let result = null // console.log(institutionFilter) // console.log(userTypeFilter) - request.input('published') != null - - const result = await Database - .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', - 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', - 'cases.author_grade', 'cases.published', 'users.username', - 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', - 'institutions.country AS institution_country', 'cases.created_at']) - .distinct('cases.id') - .from('cases') - .leftJoin('permissions', 'cases.id', 'permissions.table_id') - .join('users', 'users.id', 'cases.author_id') - .join('institutions', 'users.institution_id', 'institutions.id') - .where('cases.published', '>=', publishedFilter) - .where('cases.institution_id', 'like', institutionFilter) - .where('cases.author_grade', 'like', userTypeFilter) - .where(function(){ - if (specialtyFilter != '%') - this.where('cases.specialty', 'like', specialtyFilter) - }) - - .where(function(){ - this - .where('cases.author_id', user.id) - .orWhere(function () { - this - .where('permissions.entity', 'institution') - .where('permissions.subject', user.institution_id) - .where('permissions.clearance', '>=', clearance) + if(propertyFilter != null){ + const selectPropertyTitle = ('case_properties.value AS ' + propertyFilter) + result = await Database + .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', + 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', + 'cases.author_grade', 'cases.published', 'users.username', + 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', + 'institutions.country AS institution_country', 'cases.created_at', + Database.raw(`CASE WHEN case_properties.value = 0 AND properties.title = 'feedback' + THEN 'Waiting for feedback' WHEN case_properties.value = 1 AND properties.title = 'feedback' + THEN 'Feedback complete' ELSE case_properties.value END AS ?`,[propertyFilter])]) + .distinct('cases.id') + .from('cases') + .leftJoin('permissions', 'cases.id', 'permissions.table_id') + .join('case_properties', 'case_properties.case_id', 'cases.id') + .join('properties', 'properties.id', 'case_properties.property_id') + .join('users', 'users.id', 'cases.author_id') + .join('institutions', 'users.institution_id', 'institutions.id') + .where('properties.title', propertyFilter) + .where('case_properties.value','like', propertyValueFilter) + .where('cases.published', '>=', publishedFilter) + .where('cases.institution_id', 'like', institutionFilter) + .where('cases.author_grade', 'like', userTypeFilter) + .where(function(){ + if (specialtyFilter != '%') + this.where('cases.specialty', 'like', specialtyFilter) + }) + + .where(function(){ + this + .where('cases.author_id', user.id) + .orWhere(function () { + this + .where('permissions.entity', 'institution') + .where('permissions.subject', user.institution_id) + .where('permissions.clearance', '>=', clearance) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', user.grade) + }) + }) + }) + .orderBy('cases.created_at', 'desc') + }else{ + + result = await Database + .select([ 'cases.id', 'cases.title','cases.description', 'cases.language', 'cases.domain', + 'cases.specialty', 'cases.keywords', 'cases.complexity', 'cases.original_date', + 'cases.author_grade', 'cases.published', 'users.username', + 'institutions.title AS institution', 'institutions.acronym AS institution_acronym', + 'institutions.country AS institution_country', 'cases.created_at']) + .distinct('cases.id') + .from('cases') + .leftJoin('permissions', 'cases.id', 'permissions.table_id') + .join('users', 'users.id', 'cases.author_id') + .join('institutions', 'users.institution_id', 'institutions.id') + .where('cases.published', '>=', publishedFilter) + .where('cases.institution_id', 'like', institutionFilter) + .where('cases.author_grade', 'like', userTypeFilter) + .where(function(){ + if (specialtyFilter != '%') + this.where('cases.specialty', 'like', specialtyFilter) + }) + .where(function(){ this - .whereNull('permissions.subject_grade') - .orWhere('permissions.subject_grade', user.grade) + .where('cases.author_id', user.id) + .orWhere(function () { + this + .where('permissions.entity', 'institution') + .where('permissions.subject', user.institution_id) + .where('permissions.clearance', '>=', clearance) + .where(function(){ + this + .whereNull('permissions.subject_grade') + .orWhere('permissions.subject_grade', user.grade) + }) + }) }) - }) - }) - .orderBy('cases.created_at', 'desc') + .orderBy('cases.created_at', 'desc') + } console.log(result) From 182f17294a860a41de3958cfffdaa9ca0570dd3d Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Sun, 7 Feb 2021 16:49:45 -0300 Subject: [PATCH 14/15] feat (postman): property endpoint and case share changes --- harena-manager.postman_collection.json | 153 ++++++++++++++++++++++--- 1 file changed, 136 insertions(+), 17 deletions(-) diff --git a/harena-manager.postman_collection.json b/harena-manager.postman_collection.json index 313acf4..8b65380 100644 --- a/harena-manager.postman_collection.json +++ b/harena-manager.postman_collection.json @@ -38,12 +38,12 @@ "formdata": [ { "key": "email", - "value": "jacinto@email.com", + "value": "", "type": "text" }, { "key": "password", - "value": "jacinto", + "value": "", "type": "text" }, { @@ -351,7 +351,8 @@ { "key": "clearance", "value": "4", - "type": "text" + "type": "text", + "disabled": true }, { "key": "published", @@ -376,6 +377,18 @@ "value": "0", "type": "text", "disabled": true + }, + { + "key": "fProperty", + "value": "feedback", + "type": "text", + "disabled": true + }, + { + "key": "fPropertyValue", + "value": "1", + "type": "text", + "disabled": true } ] }, @@ -560,7 +573,8 @@ { "key": "login", "value": "jacinta", - "type": "text" + "type": "text", + "disabled": true }, { "key": "grade", @@ -663,17 +677,29 @@ "item": [ { "name": "/case/:id", + "protocolProfileBehavior": { + "disableBodyPruning": true + }, "request": { "method": "GET", "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "caseId", + "value": "", + "type": "text" + } + ] + }, "url": { - "raw": "{{api-base-url}}/case/{{case-id}}", + "raw": "{{api-base-url}}/case", "host": [ "{{api-base-url}}" ], "path": [ - "case", - "{{case-id}}" + "case" ] } }, @@ -930,14 +956,24 @@ "request": { "method": "DELETE", "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "caseId", + "value": "", + "type": "text" + } + ] + }, "url": { - "raw": "{{api-base-url}}/case/{{case-id}}", + "raw": "{{api-base-url}}/case/", "host": [ "{{api-base-url}}" ], "path": [ "case", - "{{case-id}}" + "" ] } }, @@ -961,6 +997,13 @@ "value": "c5562bfd-9a94-40f0-b08a-3627e3e417e0", "type": "text" }, + { + "key": "subject_grade", + "value": "", + "description": "Choose a specific user grade (professor/aluno)", + "type": "text", + "disabled": true + }, { "key": "clearance", "value": "4", @@ -968,8 +1011,8 @@ }, { "key": "table_id", - "value": "e6535d2e-28d9-4493-b61d-c715f56f812f", - "description": "Separate by comma if you want multiple ids", + "value": "0008f7a0-6635-439d-af22-d0edd6e22138", + "description": "Case ids. Separated by comma if you want multiple ids", "type": "text" } ] @@ -986,6 +1029,82 @@ } }, "response": [] + }, + { + "name": "/property", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "case_id", + "value": "88ffeb32-df75-43b4-a7bb-937051cff61e", + "type": "text" + }, + { + "key": "property_title", + "value": "casepropertynovo", + "type": "text" + }, + { + "key": "property_value", + "value": "novissimo", + "type": "text" + } + ] + }, + "url": { + "raw": "{{api-base-url}}/case/property", + "host": [ + "{{api-base-url}}" + ], + "path": [ + "case", + "property" + ] + } + }, + "response": [] + }, + { + "name": "/property", + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "case_id", + "value": "af19035f-df50-4178-8f9c-bc0eab59e9bd", + "type": "text" + }, + { + "key": "property_title", + "value": "feedback", + "type": "text" + }, + { + "key": "property_value", + "value": "0", + "type": "text" + } + ] + }, + "url": { + "raw": "{{api-base-url}}/case/property", + "host": [ + "{{api-base-url}}" + ], + "path": [ + "case", + "property" + ] + } + }, + "response": [] } ] }, @@ -1626,22 +1745,22 @@ "method": "PUT", "header": [], "url": { - "raw": "{{api-base-url}}/category/desafio-pocus?artifactId=desafio-pocus-image&title=Desafio Pocus", + "raw": "{{api-base-url}}/category/pocus-training?artifactId=093ebf5d-5cec-48b3-8730-12f92e8a1ffd&title=Treinamento POCUS", "host": [ "{{api-base-url}}" ], "path": [ "category", - "desafio-pocus" + "pocus-training" ], "query": [ { "key": "artifactId", - "value": "desafio-pocus-image" + "value": "093ebf5d-5cec-48b3-8730-12f92e8a1ffd" }, { "key": "title", - "value": "Desafio Pocus" + "value": "Treinamento POCUS" } ] } @@ -1871,12 +1990,12 @@ "formdata": [ { "key": "userId", - "value": "781c4351-16d7-4b24-b214-bb9fdb3e75bf", + "value": "ec4ab025-879d-4e8b-b4d1-2b5e847c08e0", "type": "text" }, { "key": "roleId", - "value": "41353296-c9ac-4365-83b6-4c9dbc845930", + "value": "74448d95-fd3f-4dc1-a424-cf73c97ced45", "type": "text" } ] From 78c09ced9faec4eec26197c25ae169a453159ee2 Mon Sep 17 00:00:00 2001 From: Heitor Mattosinho Date: Sun, 7 Feb 2021 17:59:56 -0300 Subject: [PATCH 15/15] fix(initialSeeder/Property): fix Model path --- src/adonisjs/database/seeds/InitialSeeder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adonisjs/database/seeds/InitialSeeder.js b/src/adonisjs/database/seeds/InitialSeeder.js index ed7f677..97e3c91 100644 --- a/src/adonisjs/database/seeds/InitialSeeder.js +++ b/src/adonisjs/database/seeds/InitialSeeder.js @@ -14,7 +14,7 @@ const Factory = use('Factory') const Institution = use('App/Models/v1/Institution') -const Property = use('App/Models/Property') +const Property = use('App/Models/v1/Property') const CaseArtifacts = use('App/Models/CaseArtifact') const CaseVersion = use('App/Models/v1/CaseVersion') const Case = use('App/Models/v1/Case')