mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 10:19:20 +03:00
feat: added last login column & about column to user model
This commit is contained in:
parent
7e81d7b4ff
commit
a0cba27c48
@ -12,6 +12,7 @@ import MeService from 'App/Services/MeService';
|
|||||||
*/
|
*/
|
||||||
import ChangePasswordValidator from 'App/Validators/Password/ChangePasswordValidator';
|
import ChangePasswordValidator from 'App/Validators/Password/ChangePasswordValidator';
|
||||||
import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValidator';
|
import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValidator';
|
||||||
|
import UpdateUserInfoValidator from 'App/Validators/User/UpdateUserInfoValidator';
|
||||||
|
|
||||||
import BaseController from '../../BaseController';
|
import BaseController from '../../BaseController';
|
||||||
|
|
||||||
@ -108,6 +109,21 @@ export default class MeController extends BaseController {
|
|||||||
|
|
||||||
return this.sendResponse(ctx, result.data, result.message, result.status);
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update personal info of user
|
||||||
|
* PATCH /me/info
|
||||||
|
*/
|
||||||
|
public async updateInfo(ctx: HttpContextContract) {
|
||||||
|
const payload = await ctx.request.validate(UpdateUserInfoValidator);
|
||||||
|
const result = await this.meService.updateUserInfo(payload, ctx.auth);
|
||||||
|
|
||||||
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new Ioc().make(MeController);
|
new Ioc().make(MeController);
|
||||||
|
|||||||
@ -70,6 +70,12 @@ export default class User extends BaseModel {
|
|||||||
})
|
})
|
||||||
public lessons_progress: HasMany<typeof LessonProgress>;
|
public lessons_progress: HasMany<typeof LessonProgress>;
|
||||||
|
|
||||||
|
@column()
|
||||||
|
public about: string | null;
|
||||||
|
|
||||||
|
@column.dateTime()
|
||||||
|
public last_login: DateTime | null;
|
||||||
|
|
||||||
@column.dateTime({ autoCreate: true })
|
@column.dateTime({ autoCreate: true })
|
||||||
public createdAt: DateTime;
|
public createdAt: DateTime;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import Hash from '@ioc:Adonis/Core/Hash';
|
import Hash from '@ioc:Adonis/Core/Hash';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models
|
* Models
|
||||||
@ -11,6 +12,7 @@ import Role from 'App/Models/Role';
|
|||||||
*/
|
*/
|
||||||
import CreateUserValidator from 'App/Validators/User/CreateUserValidator';
|
import CreateUserValidator from 'App/Validators/User/CreateUserValidator';
|
||||||
import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator';
|
import UpdateUserValidator from 'App/Validators/User/UpdateUserValidator';
|
||||||
|
import UpdateUserInfoValidator from 'App/Validators/User/UpdateUserInfoValidator';
|
||||||
|
|
||||||
export default class UserRepository {
|
export default class UserRepository {
|
||||||
private User: typeof User;
|
private User: typeof User;
|
||||||
@ -159,6 +161,31 @@ export default class UserRepository {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the time of last login column in database for user
|
||||||
|
*
|
||||||
|
* @param id User id
|
||||||
|
*/
|
||||||
|
public async updateLastLogin(id: number | string) {
|
||||||
|
await this.User.query().where('id', id).update({ last_login: DateTime.now() }).first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update personal info of user
|
||||||
|
*
|
||||||
|
* @param data New fields
|
||||||
|
*/
|
||||||
|
public async updateInfo(id: string | number, data: UpdateUserInfoValidator['schema']['props']) {
|
||||||
|
const user = await this.User.query().preload('contacts').preload('roles').where('id', id).first();
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
await user.merge(data).save();
|
||||||
|
return { about: user.about };
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrite all user roles
|
* Rewrite all user roles
|
||||||
*
|
*
|
||||||
|
|||||||
@ -70,8 +70,16 @@ export default class AuthService {
|
|||||||
userName: user.fullname,
|
userName: user.fullname,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cookie toke to response
|
||||||
|
*/
|
||||||
ctx.response.cookie('token', token.token);
|
ctx.response.cookie('token', token.token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save last login date
|
||||||
|
*/
|
||||||
|
await this.userRepository.updateLastLogin(user.id);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
status: HttpStatusEnum.OK,
|
status: HttpStatusEnum.OK,
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import UpdateContactsValidator from 'App/Validators/Contacts/UpdateContactsValid
|
|||||||
import CodeErrorEnum from 'App/Datatypes/Enums/CodeErrorEnum';
|
import CodeErrorEnum from 'App/Datatypes/Enums/CodeErrorEnum';
|
||||||
import RoleHelper from 'App/Helpers/RoleHelper';
|
import RoleHelper from 'App/Helpers/RoleHelper';
|
||||||
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
||||||
|
import UpdateUserInfoValidator from 'App/Validators/User/UpdateUserInfoValidator';
|
||||||
|
|
||||||
@inject()
|
@inject()
|
||||||
export default class MeService {
|
export default class MeService {
|
||||||
@ -279,6 +280,37 @@ export default class MeService {
|
|||||||
data: user.contacts,
|
data: user.contacts,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateUserInfo(
|
||||||
|
data: UpdateUserInfoValidator['schema']['props'],
|
||||||
|
auth: AuthContract
|
||||||
|
): Promise<IResponse> {
|
||||||
|
const user = await auth.use(this.authGuard).authenticate();
|
||||||
|
const info = await this.userRepository.updateInfo(user.id, data);
|
||||||
|
|
||||||
|
if (info) {
|
||||||
|
const { about } = info;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: HttpStatusEnum.OK,
|
||||||
|
message: 'User info updated.',
|
||||||
|
data: {
|
||||||
|
about,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: HttpStatusEnum.SERVICE_UNAVAILABLE,
|
||||||
|
message: 'Cannot update personal info.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_SERVICE_UNAVAILABLE',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new Ioc().make(MeService);
|
new Ioc().make(MeService);
|
||||||
|
|||||||
12
app/Validators/User/UpdateUserInfoValidator.ts
Normal file
12
app/Validators/User/UpdateUserInfoValidator.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { schema } from '@ioc:Adonis/Core/Validator';
|
||||||
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
|
||||||
|
export default class UpdateUserInfoValidator {
|
||||||
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
|
public schema = schema.create({
|
||||||
|
about: schema.string.optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
public messages = {};
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ export default class UpdateUserValidator {
|
|||||||
public schema = schema.create({
|
public schema = schema.create({
|
||||||
first_name: schema.string.optional(),
|
first_name: schema.string.optional(),
|
||||||
last_name: schema.string.optional(),
|
last_name: schema.string.optional(),
|
||||||
|
about: schema.string.optional(),
|
||||||
login: schema.string.optional({}, [rules.unique({ table: 'users', column: 'login' })]),
|
login: schema.string.optional({}, [rules.unique({ table: 'users', column: 'login' })]),
|
||||||
email: schema.string.optional({}, [rules.email(), rules.unique({ table: 'users', column: 'email' })]),
|
email: schema.string.optional({}, [rules.email(), rules.unique({ table: 'users', column: 'email' })]),
|
||||||
password: schema.string.optional(),
|
password: schema.string.optional(),
|
||||||
|
|||||||
@ -8,9 +8,11 @@ export default class Users extends BaseSchema {
|
|||||||
table.string('id', 21).primary();
|
table.string('id', 21).primary();
|
||||||
table.string('first_name', 24).notNullable();
|
table.string('first_name', 24).notNullable();
|
||||||
table.string('last_name', 24).notNullable();
|
table.string('last_name', 24).notNullable();
|
||||||
|
table.text('about');
|
||||||
table.string('login', 128).notNullable().unique();
|
table.string('login', 128).notNullable().unique();
|
||||||
table.string('email').notNullable().unique();
|
table.string('email').notNullable().unique();
|
||||||
table.string('password').notNullable();
|
table.string('password').notNullable();
|
||||||
|
table.timestamp('last_login', { useTz: true });
|
||||||
table.timestamp('created_at', { useTz: true });
|
table.timestamp('created_at', { useTz: true });
|
||||||
table.timestamp('updated_at', { useTz: true });
|
table.timestamp('updated_at', { useTz: true });
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import Route from '@ioc:Adonis/Core/Route';
|
|||||||
|
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
Route.get('/', 'Api/v1/MeController.show').middleware('role:admin,teacher,student').as('me.show');
|
Route.get('/', 'Api/v1/MeController.show').middleware('role:admin,teacher,student').as('me.show');
|
||||||
|
Route.patch('/info', 'Api/v1/MeController.updateInfo').middleware('role:admin,teacher,student').as('me.update-info');
|
||||||
Route.patch('/email', 'Api/v1/MeController.changeEmail')
|
Route.patch('/email', 'Api/v1/MeController.changeEmail')
|
||||||
.middleware('role:admin,teacher,student')
|
.middleware('role:admin,teacher,student')
|
||||||
.as('me.change-email');
|
.as('me.change-email');
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user