mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 18:29:15 +03:00
some refactoring
This commit is contained in:
parent
7056568c26
commit
e50700c2ab
@ -16,9 +16,6 @@ export default class AuthController {
|
|||||||
/**
|
/**
|
||||||
* Creates a new token for user and returns it.
|
* Creates a new token for user and returns it.
|
||||||
* POST /login
|
* POST /login
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {object} - Token data
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async login({ auth, request }: HttpContextContract) {
|
public async login({ auth, request }: HttpContextContract) {
|
||||||
@ -43,13 +40,10 @@ export default class AuthController {
|
|||||||
/**
|
/**
|
||||||
* Revoke a token if user logged in.
|
* Revoke a token if user logged in.
|
||||||
* POST /logout
|
* POST /logout
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {object} - Revoked message
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async logout({ auth }: HttpContextContract) {
|
public async logout({ response, auth }: HttpContextContract) {
|
||||||
await auth.use(this.guard).revoke();
|
await auth.use(this.guard).revoke();
|
||||||
return { message: 'REVOKED' };
|
return response.noContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
// import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
|
||||||
|
|
||||||
export default class ContactsController {
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
import { Exception } from '@adonisjs/core/build/standalone';
|
|
||||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
|
||||||
|
|
||||||
import Role from 'App/Models/Role';
|
|
||||||
import User from 'App/Models/User';
|
|
||||||
import AddRoleToUserValidator from 'App/Validators/AddRoleToUserValidator';
|
|
||||||
import DelRoleFromUserValidator from 'App/Validators/DelRoleFromUserValidator';
|
|
||||||
|
|
||||||
export default class RolesController {
|
|
||||||
private readonly user: typeof User;
|
|
||||||
|
|
||||||
private readonly role: typeof Role;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.user = User;
|
|
||||||
this.role = Role;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async findRolesBySlug(input: any) {
|
|
||||||
const roles = await this.role.query().whereIn('slug', input);
|
|
||||||
|
|
||||||
if (roles.length !== input.length) {
|
|
||||||
throw new Exception(
|
|
||||||
'Unable to find any role using input value "roles"',
|
|
||||||
404,
|
|
||||||
'E_ROLE_NOT_FOUND'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a role to a user by "id"
|
|
||||||
* POST /user/:id/roles
|
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {Promise<User>} - Updated user.
|
|
||||||
*/
|
|
||||||
public async store({ request, params }: HttpContextContract): Promise<Role[]> {
|
|
||||||
try {
|
|
||||||
await request.validate(AddRoleToUserValidator);
|
|
||||||
|
|
||||||
const input = request.input('roles');
|
|
||||||
const user = await this.user.findOrFail(params.id);
|
|
||||||
const roles = await this.findRolesBySlug(input);
|
|
||||||
|
|
||||||
await user.related('roles').attach(roles.map(r => r.id));
|
|
||||||
await user.load('roles');
|
|
||||||
|
|
||||||
return user.roles;
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code === '23505') {
|
|
||||||
throw new Exception('Some role already attached to that user.', 400, 'E_ROLE_ATTACHED');
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detach role from user by "id"
|
|
||||||
* DELETE /users/:id/roles
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public async destroy({ request, params }: HttpContextContract): Promise<Role[]> {
|
|
||||||
await request.validate(DelRoleFromUserValidator);
|
|
||||||
|
|
||||||
const input = request.input('roles');
|
|
||||||
const user = await this.user.query().preload('roles').where('id', params.id).firstOrFail();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detach all when "roles" input not provided
|
|
||||||
*/
|
|
||||||
if (input === undefined) {
|
|
||||||
user.related('roles').detach([]);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const roles = await this.findRolesBySlug(input);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if role is attached to user before detach
|
|
||||||
*/
|
|
||||||
roles.forEach(role => {
|
|
||||||
if (!user.roles.map(r => r.id).includes(role.id)) {
|
|
||||||
throw new Exception(
|
|
||||||
`Role "${role.slug}" does not attached to that user.`,
|
|
||||||
400,
|
|
||||||
'E_ROLE_NOT_ATTACHED'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
user.related('roles').detach(roles.map(r => r.id));
|
|
||||||
await user.load('roles');
|
|
||||||
|
|
||||||
return user.roles;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +1,11 @@
|
|||||||
|
import { Exception } from '@adonisjs/core/build/standalone';
|
||||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
import Contact from 'App/Models/Contact';
|
||||||
import Role from 'App/Models/Role';
|
import Role from 'App/Models/Role';
|
||||||
import User from 'App/Models/User';
|
import User from 'App/Models/User';
|
||||||
import Contact from 'App/Models/Contact';
|
import AddRoleToUserValidator from 'App/Validators/AddRoleToUserValidator';
|
||||||
import CreateUserValidator from 'App/Validators/CreateUserValidator';
|
import CreateUserValidator from 'App/Validators/CreateUserValidator';
|
||||||
|
import DelRoleFromUserValidator from 'App/Validators/DelRoleFromUserValidator';
|
||||||
import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
|
import UpdateUserValidator from 'App/Validators/UpdateUserValidator';
|
||||||
|
|
||||||
export default class UsersController {
|
export default class UsersController {
|
||||||
@ -19,27 +22,51 @@ export default class UsersController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a list of all users.
|
* Attach array of roles to user
|
||||||
* GET /users
|
* POST /users/:id/attach_roles
|
||||||
*
|
|
||||||
* @returns {Promise<User[]>}
|
|
||||||
*/
|
*/
|
||||||
|
public async attach_roles({ request, response, params }: HttpContextContract) {
|
||||||
|
await request.validate(AddRoleToUserValidator);
|
||||||
|
|
||||||
public async index(): Promise<User[]> {
|
const input: string[] | undefined = request.input('roles');
|
||||||
const users = await this.user.query().preload('contacts').preload('roles');
|
const user = await this.user.query().preload('roles').where('id', params.id).firstOrFail();
|
||||||
return users;
|
const roles = await this.findRolesBySlug(input);
|
||||||
|
|
||||||
|
await this.user.attachRoles(user, roles);
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: 'Roles attached',
|
||||||
|
data: user.roles,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a current user by "id" parameter.
|
* Detach array of roles from user
|
||||||
* GET /users/:id
|
* DELETE /users/:id/detach_roles
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {Promise<User>}
|
|
||||||
*/
|
*/
|
||||||
|
public async detach_roles({ request, response, params }: HttpContextContract) {
|
||||||
|
await request.validate(DelRoleFromUserValidator);
|
||||||
|
|
||||||
public async show({ params }: HttpContextContract): Promise<User> {
|
const input: string[] | undefined = request.input('roles');
|
||||||
const user = await this.user.findOrFail(params.id);
|
const user = await this.user.query().preload('roles').where('id', params.id).firstOrFail();
|
||||||
|
const roles = await this.findRolesBySlug(input);
|
||||||
|
|
||||||
|
await this.user.detachRoles(user, roles);
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: 'Roles detached',
|
||||||
|
data: user.roles,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows user info of the access token resource owner.
|
||||||
|
* GET /users/me
|
||||||
|
*/
|
||||||
|
public async me({ auth: { user } }: HttpContextContract): Promise<User> {
|
||||||
|
if (!user) {
|
||||||
|
throw new AuthenticationException('Unauthorized access', 'E_UNAUTHORIZED_ACCESS');
|
||||||
|
}
|
||||||
|
|
||||||
await user.load('contacts');
|
await user.load('contacts');
|
||||||
await user.load('roles');
|
await user.load('roles');
|
||||||
@ -48,17 +75,44 @@ export default class UsersController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new user in a system.
|
* Show a list of all users.
|
||||||
* POST /users
|
* GET /users
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {Promise<User>} - Created user.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async store({ request }: HttpContextContract): Promise<User> {
|
public async index({ response }: HttpContextContract) {
|
||||||
|
const users = await this.user.query().preload('contacts').preload('roles');
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: 'Fetched all users.',
|
||||||
|
data: users,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a current user by "id" parameter.
|
||||||
|
* GET /users/:id
|
||||||
|
*/
|
||||||
|
|
||||||
|
public async show({ response, params }: HttpContextContract) {
|
||||||
|
const user = await this.user.findOrFail(params.id);
|
||||||
|
|
||||||
|
await user.load('contacts');
|
||||||
|
await user.load('roles');
|
||||||
|
|
||||||
|
return response.ok({
|
||||||
|
message: `Fetched user with id: "${user.id}"`,
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new user in a system.
|
||||||
|
* POST /users
|
||||||
|
*/
|
||||||
|
|
||||||
|
public async store({ response, request }: HttpContextContract) {
|
||||||
await request.validate(CreateUserValidator);
|
await request.validate(CreateUserValidator);
|
||||||
|
|
||||||
const roles = await this.role.query().whereIn('slug', request.input('roles'));
|
|
||||||
const user = await this.user.create({
|
const user = await this.user.create({
|
||||||
first_name: request.input('first_name'),
|
first_name: request.input('first_name'),
|
||||||
last_name: request.input('last_name'),
|
last_name: request.input('last_name'),
|
||||||
@ -67,69 +121,94 @@ export default class UsersController {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await user.related('contacts').create({ email: request.input('email') });
|
await user.related('contacts').create({ email: request.input('email') });
|
||||||
await user.related('roles').attach(roles.map(r => r.id));
|
|
||||||
|
|
||||||
await user.load('roles');
|
|
||||||
await user.load('contacts');
|
await user.load('contacts');
|
||||||
|
|
||||||
return user;
|
return response.created({ message: 'Successfully created.', data: user });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a user in a system by "id".
|
* Update a user in a system by "id".
|
||||||
* PATCH /users/:id
|
* PATCH /users/:id
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {Promise<User>}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async update({ request, params }: HttpContextContract): Promise<User> {
|
public async update({ request, response, params }: HttpContextContract) {
|
||||||
await request.validate(UpdateUserValidator);
|
await request.validate(UpdateUserValidator);
|
||||||
|
|
||||||
/**
|
|
||||||
* User update
|
|
||||||
*/
|
|
||||||
const user = await this.user.findOrFail(params.id);
|
const user = await this.user.findOrFail(params.id);
|
||||||
user.first_name = request.input('first_name');
|
const dataInput: Pick<User, 'first_name' | 'last_name' | 'login' | 'password'> = {
|
||||||
user.last_name = request.input('last_name');
|
first_name: request.input('first_name'),
|
||||||
user.login = request.input('login');
|
last_name: request.input('last_name'),
|
||||||
user.password = request.input('password');
|
login: request.input('login'),
|
||||||
|
password: request.input('password'),
|
||||||
// await user.load('roles');
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contacts update
|
* Update only provided input roles value.
|
||||||
*/
|
*/
|
||||||
const contacts = await this.contact.findByOrFail('user_id', params.id);
|
Object.keys(dataInput).forEach(k => {
|
||||||
contacts.email = request.input('email');
|
if (dataInput[k] !== undefined) {
|
||||||
|
user[k] = dataInput[k];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the updated data
|
|
||||||
*/
|
|
||||||
await user.save();
|
await user.save();
|
||||||
await contacts.save();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the updated data to return
|
|
||||||
*/
|
|
||||||
await user.load('roles');
|
await user.load('roles');
|
||||||
await user.load('contacts');
|
await user.load('contacts');
|
||||||
|
|
||||||
return user;
|
return response.ok({
|
||||||
|
message: `User with id: "${user.id}" was successfully updated.`,
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a user by "id".
|
* Delete a user by "id".
|
||||||
* DELETE /users
|
* DELETE /users/:id
|
||||||
*
|
|
||||||
* @param {HttpContextContract} context
|
|
||||||
* @returns {Promise<User>}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public async destroy({ params }: HttpContextContract): Promise<User> {
|
public async destroy({ response, params }: HttpContextContract) {
|
||||||
const user = await this.user.findOrFail(params.id);
|
const user = await this.user
|
||||||
|
.query()
|
||||||
|
.preload('contacts')
|
||||||
|
.preload('roles')
|
||||||
|
.where('id', params.id)
|
||||||
|
.firstOrFail();
|
||||||
|
|
||||||
await user.delete();
|
await user.delete();
|
||||||
|
|
||||||
return user;
|
return response.ok({
|
||||||
|
message: `Used with id: "${user.id}" was successfully deleted.`,
|
||||||
|
data: user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds roles by input value and throw error if role does not exist.
|
||||||
|
*
|
||||||
|
* @param input Array of roles to find them
|
||||||
|
* @returns Finded roles
|
||||||
|
*/
|
||||||
|
private async findRolesBySlug(input: string[] | undefined): Promise<Role[]> {
|
||||||
|
if (!input) {
|
||||||
|
throw new Exception(
|
||||||
|
'Unable to find "roles" field in input.',
|
||||||
|
400,
|
||||||
|
'E_ROLES_FIELD_NOT_PROVIDED'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const roles = await this.role.query().whereIn('slug', input);
|
||||||
|
|
||||||
|
input.forEach(val => {
|
||||||
|
if (!roles.map(r => r.slug).includes(val)) {
|
||||||
|
throw new Exception(
|
||||||
|
`Unable to find role: "${val}" using input value "roles"`,
|
||||||
|
404,
|
||||||
|
'E_ROLE_NOT_FOUND'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return roles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
/* eslint-disable import/no-cycle */
|
/* eslint-disable import/no-cycle */
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
import { Exception } from '@adonisjs/core/build/standalone';
|
||||||
import {
|
import {
|
||||||
BaseModel,
|
BaseModel,
|
||||||
beforeCreate,
|
beforeCreate,
|
||||||
@ -48,11 +49,62 @@ export default class User extends BaseModel {
|
|||||||
@column.dateTime({ autoCreate: true, autoUpdate: true, serializeAs: null })
|
@column.dateTime({ autoCreate: true, autoUpdate: true, serializeAs: null })
|
||||||
public updatedAt: DateTime;
|
public updatedAt: DateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input role is already attached, and if so, throws an error,
|
||||||
|
* otherwise it attaches the role to the user.
|
||||||
|
*
|
||||||
|
* @param user User
|
||||||
|
* @param inputRoles Array of roles to attach
|
||||||
|
*/
|
||||||
|
public static async attachRoles(user: User, inputRoles: Role[]): Promise<void> {
|
||||||
|
const currentRolesSlugs: string[] = user.roles.map(r => r.slug);
|
||||||
|
const inputRolesSlugs: string[] = inputRoles.map(r => r.slug);
|
||||||
|
|
||||||
|
currentRolesSlugs.forEach(s => {
|
||||||
|
if (inputRolesSlugs.includes(s)) {
|
||||||
|
throw new Exception(`Role "${s}" already attached to that user.`, 400, 'E_ROLE_ATTACHED');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.related('roles').attach(inputRoles.map(r => r.id));
|
||||||
|
await user.load('roles'); // load updated roles
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before detach, checks if input role is attached to that user and
|
||||||
|
* if not, throws an error.
|
||||||
|
*
|
||||||
|
* @param user User
|
||||||
|
* @param inputRoles Array of roles to detach
|
||||||
|
*/
|
||||||
|
public static async detachRoles(user: User, inputRoles: Role[]): Promise<void> {
|
||||||
|
inputRoles.forEach(role => {
|
||||||
|
if (!user.roles.map(r => r.id).includes(role.id)) {
|
||||||
|
throw new Exception(
|
||||||
|
`Role "${role.slug}" not attached to that user.`,
|
||||||
|
400,
|
||||||
|
'E_ROLE_NOT_ATTACHED'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
user.related('roles').detach(inputRoles.map(r => r.id));
|
||||||
|
await user.load('roles');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign id to user by nanoid.
|
||||||
|
* @param user User
|
||||||
|
*/
|
||||||
@beforeCreate()
|
@beforeCreate()
|
||||||
public static assignUui(user: User) {
|
public static assignUui(user: User) {
|
||||||
user.id = nanoid();
|
user.id = nanoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash password before save
|
||||||
|
* @param user User
|
||||||
|
*/
|
||||||
@beforeSave()
|
@beforeSave()
|
||||||
public static async hashPassword(user: User) {
|
public static async hashPassword(user: User) {
|
||||||
if (user.$dirty.password) {
|
if (user.$dirty.password) {
|
||||||
|
|||||||
@ -5,14 +5,16 @@ export default class UpdateUserValidator {
|
|||||||
constructor(protected ctx: HttpContextContract) {}
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
public schema = schema.create({
|
public schema = schema.create({
|
||||||
first_name: schema.string.optional(),
|
first_name: schema.string.optional({}, [
|
||||||
last_name: schema.string.optional(),
|
rules.unique({ table: 'users', column: 'first_name' }),
|
||||||
|
]),
|
||||||
|
last_name: schema.string.optional({}, [rules.unique({ table: 'users', column: 'last_name' })]),
|
||||||
login: schema.string.optional({}, [rules.unique({ table: 'users', column: 'login' })]),
|
login: schema.string.optional({}, [rules.unique({ table: 'users', column: 'login' })]),
|
||||||
email: schema.string.optional({}, [
|
email: schema.string.optional({}, [
|
||||||
rules.email(),
|
rules.email(),
|
||||||
rules.unique({ table: 'contacts', column: 'email' }),
|
rules.unique({ table: 'contacts', column: 'email' }),
|
||||||
]),
|
]),
|
||||||
password: schema.string.optional(),
|
password: schema.string.optional({}, [rules.unique({ table: 'users', column: 'password' })]),
|
||||||
});
|
});
|
||||||
|
|
||||||
public messages = {};
|
public messages = {};
|
||||||
|
|||||||
@ -20,21 +20,25 @@
|
|||||||
|
|
||||||
import Route from '@ioc:Adonis/Core/Route';
|
import Route from '@ioc:Adonis/Core/Route';
|
||||||
|
|
||||||
Route.get('/', () => `API REST Server.`);
|
Route.get('/', () => `Educt Backend API.`);
|
||||||
|
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
/* Auth */
|
/* Auth controller */
|
||||||
Route.post('login', 'AuthController.login');
|
Route.post('login', 'AuthController.login');
|
||||||
Route.post('logout', 'AuthController.logout').middleware('auth');
|
Route.post('logout', 'AuthController.logout').middleware('auth');
|
||||||
|
|
||||||
/* API */
|
/* API */
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
|
/**
|
||||||
|
* Users controller
|
||||||
|
*/
|
||||||
|
Route.get('users/me', 'UsersController.me').middleware('role:admin,teacher,student');
|
||||||
Route.get('users', 'UsersController.index').middleware('role:admin,teacher,student');
|
Route.get('users', 'UsersController.index').middleware('role:admin,teacher,student');
|
||||||
Route.get('users/:id', 'UsersController.show').middleware('role:admin,teacher,student');
|
Route.get('users/:id', 'UsersController.show').middleware('role:admin,teacher,student');
|
||||||
Route.post('users', 'UsersController.store').middleware('role:admin');
|
Route.post('users', 'UsersController.store').middleware('role:admin');
|
||||||
Route.patch('users/:id', 'UsersController.update').middleware('role:admin');
|
Route.patch('users/:id', 'UsersController.update').middleware('role:admin');
|
||||||
Route.delete('users', 'UsersController.destroy').middleware('role:admin');
|
Route.delete('users/:id', 'UsersController.destroy').middleware('role:admin');
|
||||||
Route.post('users/:id/roles', 'RolesController.store').middleware('role:admin');
|
Route.post('users/:id/attach_roles', 'UsersController.attach_roles').middleware('role:admin');
|
||||||
Route.delete('users/:id/roles', 'RolesController.destroy').middleware('role:admin');
|
Route.delete('users/:id/detach_roles', 'UsersController.detach_roles').middleware('role:admin');
|
||||||
}).middleware('auth');
|
}).middleware('auth');
|
||||||
}).prefix('api');
|
}).prefix('api');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user