Skip to content
Snippets Groups Projects
Commit f4728516 authored by Nhan Luong's avatar Nhan Luong :speech_balloon:
Browse files

Merge branch 'main' into 'main'

Keep track of main branch

See merge request !11
parents 51672af5 d35d02b3
No related branches found
No related tags found
1 merge request!11Keep track of main branch
Showing
with 177 additions and 43 deletions
......@@ -4,12 +4,10 @@ RUN mkdir -p /usr/src/playground-be && chown -R node:node /usr/src/playground-be
WORKDIR /usr/src/playground-be
COPY package.json yarn.lock ./
COPY package.json ./
USER node
RUN yarn install --pure-lockfile
COPY --chown=node:node . .
EXPOSE 8080
services:
playground-be:
platform: linux/amd64
container_name: ${ENV:-dev}-playground-be
build: .
image: boschvn/playground-be:${IMAGE_TAG:-latest}
......@@ -10,7 +11,7 @@ services:
- upload
networks:
- node-network
restart: always
restart: ${RESTART_POLICY:-always}
playground-db:
container_name: ${ENV:-dev}-playground-db
......@@ -21,9 +22,10 @@ services:
- dbdata:/data/db
networks:
- node-network
restart: always
restart: ${RESTART_POLICY:-always}
upload:
platform: linux/amd64
container_name: ${ENV:-dev}-upload
build: ./upload/
image: boschvn/upload:${IMAGE_TAG:-latest}
......@@ -34,7 +36,7 @@ services:
networks:
- node-network
restart: always
restart: ${RESTART_POLICY:-always}
volumes:
dbdata:
......
......@@ -45,6 +45,10 @@ const envVarsSchema = Joi.object()
ETAS_CLIENT_SECRET: Joi.string().description('ETAS client secret'),
ETAS_SCOPE: Joi.string().description('ETAS scope'),
ETAS_INSTANCE_ENDPOINT: Joi.string().description('ETAS instance endpoint'),
// Certivity
CERTIVITY_CLIENT_ID: Joi.string().required().description('Certivity client id'),
CERTIVITY_CLIENT_SECRET: Joi.string().required().description('Certivity client secret'),
STRICT_AUTH: Joi.boolean().description('Strict auth'),
})
.unknown();
......@@ -57,6 +61,7 @@ if (error) {
const config = {
env: envVars.NODE_ENV,
port: envVars.PORT,
strictAuth: envVars.STRICT_AUTH,
mongoose: {
url: envVars.MONGODB_URL + (envVars.NODE_ENV === 'test' ? '-test' : ''),
options: {
......@@ -73,7 +78,6 @@ const config = {
resetPasswordExpirationMinutes: envVars.JWT_RESET_PASSWORD_EXPIRATION_MINUTES,
verifyEmailExpirationMinutes: envVars.JWT_VERIFY_EMAIL_EXPIRATION_MINUTES,
cookieRefreshOptions: {
// TODO: change this to true when deploy
secure: true,
httpOnly: true,
sameSite: 'None',
......@@ -138,6 +142,14 @@ const config = {
instanceEndpoint: envVars.ETAS_INSTANCE_ENDPOINT,
},
githubIssueSubmitUrl: 'https://api.github.com/repos/digital-auto/vehicle_signal_specification/issues',
certivity: {
authBaseUrl: 'https://certivity-dev.eu.auth0.com/oauth/token',
authAudience: 'https://service-api-dev.certivity.io',
authGrantType: 'client_credentials',
clientId: envVars.CERTIVITY_CLIENT_ID,
clientSecret: envVars.CERTIVITY_CLIENT_SECRET,
regulationBaseUrl: 'https://ctvt-service-api.azurewebsites.net/api/v1/protected/regulation',
},
};
if (config.env === 'development') {
......
......@@ -6,7 +6,7 @@ const config = require('../config/config');
const register = catchAsync(async (req, res) => {
const user = await userService.createUser({
...req.body,
provider: 'Email',
provider: req.body?.provider || 'Email',
});
const tokens = await tokenService.generateAuthTokens(user);
res.cookie('token', tokens.refresh.token, {
......
const { certivityService } = require('../services');
const catchAsync = require('../utils/catchAsync');
const getRegulations = catchAsync(async (req, res) => {
const credentials = await certivityService.getCredentials();
if (!credentials) {
return res.status(502).json({
message: 'Bad Gateway. Cannot retrieve credentials from Certivity',
});
}
const { vehicleApis } = req.query;
const regulations = await certivityService.getRegulations(credentials.access_token, vehicleApis);
if (!regulations) {
return res.status(502).json({
message: 'Bad Gateway. Cannot retrieve regulations from Certivity',
});
}
res.send(regulations);
});
module.exports = {
getRegulations,
};
......@@ -14,13 +14,16 @@ const createDiscussion = catchAsync(async (req, res) => {
const listDiscussions = catchAsync(async (req, res) => {
const filter = pick(req.query, ['ref', 'ref_type', 'id', 'parent']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields', 'populate']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields']);
const discussions = await discussionService.queryDiscussions(
{
...filter,
parent: { $exists: false },
},
options
{
...options,
populate: ['created_by', 'name image_file'],
}
);
// TODO: Optimize the code below
const promises = [];
......
......@@ -14,8 +14,11 @@ const createFeedback = catchAsync(async (req, res) => {
const listFeedbacks = catchAsync(async (req, res) => {
const filter = pick(req.query, ['ref', 'ref_type', 'id', 'avg_score', 'model_id', 'created_by']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields', 'populate']);
const feedbacks = await feedbackService.queryFeedbacks(filter, options);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields']);
const feedbacks = await feedbackService.queryFeedbacks(filter, {
...options,
populate: ['created_by', 'name image_file'],
});
res.send(feedbacks);
});
......
......@@ -3,7 +3,6 @@ module.exports.userController = require('./user.controller');
module.exports.modelLegacyController = require('./model.legacy.controller');
module.exports.prototypeLegacyController = require('./prototype.legacy.controller');
module.exports.tagController = require('./tag.controller');
module.exports.modelController = require('./model.controller');
module.exports.prototypeController = require('./prototype.controller');
module.exports.apiController = require('./api.controller');
......@@ -12,3 +11,4 @@ module.exports.feedbackController = require('./feedback.controller');
module.exports.issueController = require('./issue.controller');
module.exports.genaiController = require('./genai.controller');
module.exports.searchController = require('./search.controller');
module.exports.certivityController = require('./certivity.controller');
......@@ -21,7 +21,7 @@ const createModel = catchAsync(async (req, res) => {
const listModels = catchAsync(async (req, res) => {
const filter = pick(req.query, ['name', 'visibility', 'tenant_id', 'vehicle_category', 'main_api', 'id', 'created_by']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields', 'populate']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields']);
const advanced = pick(req.query, ['is_contributor']);
const models = await modelService.queryModels(filter, options, advanced, req.user?.id);
res.json(models);
......
......@@ -16,8 +16,11 @@ const createPrototype = catchAsync(async (req, res) => {
const listPrototypes = catchAsync(async (req, res) => {
const filter = pick(req.query, ['state', 'model_id', 'name', 'complexity_level', 'autorun', 'created_by']);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields', 'populate']);
const prototypes = await prototypeService.queryPrototypes(filter, options);
const options = pick(req.query, ['sortBy', 'limit', 'page', 'fields']);
const prototypes = await prototypeService.queryPrototypes(filter, {
...options,
populate: ['created_by', 'name image_file'],
});
res.send(prototypes);
});
......@@ -42,6 +45,18 @@ const listRecentPrototypes = catchAsync(async (req, res) => {
res.send(prototypes);
});
const executeCode = catchAsync(async (req, res) => {
// Check if user has permission to view the prototype
await prototypeService.getPrototypeById(req.params.id, req.user?.id);
await prototypeService.executeCode(req.params.id, req.body);
res.send('OK');
});
const listPopularPrototypes = catchAsync(async (req, res) => {
const prototypes = await prototypeService.listPopularPrototypes(req.user.id);
res.send(prototypes);
});
module.exports = {
createPrototype,
listPrototypes,
......@@ -49,4 +64,6 @@ module.exports = {
updatePrototype,
deletePrototype,
listRecentPrototypes,
listPopularPrototypes,
executeCode,
};
......@@ -4,6 +4,7 @@ const ApiError = require('../utils/ApiError');
const catchAsync = require('../utils/catchAsync');
const { userService, permissionService } = require('../services');
const { Role } = require('../models');
const { PERMISSIONS } = require('../config/roles');
const createUser = catchAsync(async (req, res) => {
const user = await userService.createUser(req.body);
......@@ -13,17 +14,34 @@ const createUser = catchAsync(async (req, res) => {
const getUsers = catchAsync(async (req, res) => {
const filter = pick(req.query, ['name', 'role']);
const options = pick(req.query, ['sortBy', 'limit', 'page']);
const result = await userService.queryUsers(filter, options);
const advanced = pick(req.query, ['search', 'includeFullDetails']);
if (advanced.includeFullDetails) {
// Check if has permission
if (!(await permissionService.hasPermission(req.user?.id, PERMISSIONS.MANAGE_USERS))) {
throw new ApiError(httpStatus.FORBIDDEN, 'Forbidden');
}
}
const result = await userService.queryUsers(filter, options, advanced);
res.send(result);
});
const getSelf = catchAsync(async (req, res) => {
const user = await userService.getUserById(req.user.id);
const user = await userService.getUserById(req.user.id, true);
res.send(user);
});
const getUser = catchAsync(async (req, res) => {
const user = await userService.getUserById(req.params.userId);
if (req.query.includeFullDetails) {
// Check if has permission
if (
req.user?.id !== req.params.userId &&
!(await permissionService.hasPermission(req.user?.id, PERMISSIONS.MANAGE_USERS))
) {
throw new ApiError(httpStatus.FORBIDDEN, 'Forbidden');
}
}
const user = await userService.getUserById(req.params.userId, req.query.includeFullDetails);
if (!user) {
throw new ApiError(httpStatus.NOT_FOUND, 'User not found');
}
......
......@@ -55,14 +55,7 @@ const paginate = (schema) => {
let docsPromise = this.find(match).sort(sort).skip(skip).limit(limit);
if (options.populate) {
options.populate.split(',').forEach((populateOption) => {
docsPromise = docsPromise.populate(
populateOption
.split('.')
.reverse()
.reduce((a, b) => ({ path: b, populate: a }))
);
});
docsPromise = docsPromise.populate(...options.populate);
}
if (options.fields) {
......
......@@ -31,7 +31,7 @@ const toJSON = (schema) => {
ret.id = ret._id.toString();
delete ret._id;
delete ret.__v;
ret.created_at = ret.createdAt;
// ret.created_at = ret.createdAt;
delete ret.createdAt;
delete ret.updatedAt;
if (transform) {
......
......@@ -186,11 +186,25 @@ const prototypeSchema = mongoose.Schema({
ref: 'User',
required: true,
},
executed_turns: {
type: Number,
default: 0,
},
});
// add plugin that converts mongoose to json
prototypeSchema.plugin(toJSON);
prototypeSchema.plugin(paginate);
prototypeSchema.set('toJSON', {
virtuals: true,
});
prototypeSchema.virtual('model', {
ref: 'Model',
localField: 'model_id',
foreignField: '_id',
justOne: true,
});
prototypeSchema.statics.existsPrototypeInModel = async function (model_id, name, excludeId) {
const prototype = await this.findOne({ name, model_id, _id: { $ne: excludeId } });
......
......@@ -40,14 +40,10 @@ const userSchema = mongoose.Schema(
minlength: 8,
private: true, // used by the toJSON plugin
},
role: {
type: String,
enum: roles,
default: 'user',
},
email_verified: {
type: Boolean,
default: false,
private: true,
},
image_file: {
type: String,
......
......@@ -3,13 +3,20 @@ const auth = require('../../middlewares/auth');
const validate = require('../../middlewares/validate');
const { apiController } = require('../../controllers');
const { apiValidation } = require('../../validations');
const config = require('../../config/config');
const router = express.Router();
router.route('/').post(auth(), validate(apiValidation.createApi), apiController.createApi);
router
.route('/:id')
.get(validate(apiValidation.getApi), apiController.getApi)
.get(
auth({
optional: !config.strictAuth,
}),
validate(apiValidation.getApi),
apiController.getApi
)
.patch(auth(), validate(apiValidation.updateApi), apiController.updateApi)
.delete(auth(), validate(apiValidation.deleteApi), apiController.deleteApi);
router.route('/model_id/:modelId').get(validate(apiValidation.getApiByModelId), apiController.getApiByModelId);
......
const express = require('express');
const validate = require('../../middlewares/validate');
const { certivityValidation } = require('../../validations');
const { certivityController } = require('../../controllers');
const config = require('../../config/config');
const auth = require('../../middlewares/auth');
const router = express.Router();
router.route('/regulations').get(
auth({
optional: !config.strictAuth,
}),
validate(certivityValidation.getRegulations),
certivityController.getRegulations
);
module.exports = router;
......@@ -3,13 +3,20 @@ const validate = require('../../middlewares/validate');
const { discussionValidation } = require('../../validations');
const { discussionController } = require('../../controllers');
const auth = require('../../middlewares/auth');
const config = require('../../config/config');
const router = express.Router();
router
.route('/')
.post(auth(), validate(discussionValidation.createDiscussion), discussionController.createDiscussion)
.get(validate(discussionValidation.listDiscussions), discussionController.listDiscussions);
.get(
auth({
optional: !config.strictAuth,
}),
validate(discussionValidation.listDiscussions),
discussionController.listDiscussions
);
router
.route('/:id')
......
......@@ -3,24 +3,38 @@ const auth = require('../../middlewares/auth');
const validate = require('../../middlewares/validate');
const extendedApiValidation = require('../../validations/extendedApi.validation');
const extendedApiController = require('../../controllers/extendedApi.controller');
const config = require('../../config/config');
const router = express.Router();
router
.route('/')
.post(auth(), validate(extendedApiValidation.createExtendedApi), extendedApiController.createExtendedApi)
.get(validate(extendedApiValidation.getExtendedApis), extendedApiController.getExtendedApis);
router
.route('/by-api-and-model')
.get(
validate(extendedApiValidation.getExtendedApiByApiNameAndModel),
extendedApiController.getExtendedApiByApiNameAndModel
auth({
optional: !config.strictAuth,
}),
validate(extendedApiValidation.getExtendedApis),
extendedApiController.getExtendedApis
);
router.route('/by-api-and-model').get(
auth({
optional: !config.strictAuth,
}),
validate(extendedApiValidation.getExtendedApiByApiNameAndModel),
extendedApiController.getExtendedApiByApiNameAndModel
);
router
.route('/:id')
.get(validate(extendedApiValidation.getExtendedApi), extendedApiController.getExtendedApi)
.get(
auth({
optional: !config.strictAuth,
}),
validate(extendedApiValidation.getExtendedApi),
extendedApiController.getExtendedApi
)
.patch(auth(), validate(extendedApiValidation.updateExtendedApi), extendedApiController.updateExtendedApi)
.delete(auth(), validate(extendedApiValidation.deleteExtendedApi), extendedApiController.deleteExtendedApi);
......
......@@ -3,13 +3,20 @@ const validate = require('../../middlewares/validate');
const auth = require('../../middlewares/auth');
const { feedbackValidation } = require('../../validations');
const { feedbackController } = require('../../controllers');
const config = require('../../config/config');
const router = express.Router();
router
.route('/')
.post(auth(), validate(feedbackValidation.createFeedback), feedbackController.createFeedback)
.get(validate(feedbackValidation.listFeedbacks), feedbackController.listFeedbacks);
.get(
auth({
optional: !config.strictAuth,
}),
validate(feedbackValidation.listFeedbacks),
feedbackController.listFeedbacks
);
router
.route('/:id')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment