Skip to content

Commit

Permalink
Merge pull request #189 from smartdevicelink/develop
Browse files Browse the repository at this point in the history
Release 2.9.0
  • Loading branch information
crokita authored Apr 30, 2020
2 parents 17a11ca + 4c8bf65 commit 7eaa6db
Show file tree
Hide file tree
Showing 15 changed files with 1,367 additions and 623 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ dist/
*.ntvs*
*.njsproj
*.sln
*.zip
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2017 - 2018 SmartDeviceLink Consortium, Inc.
Copyright (c) 2017 - 2020 SmartDeviceLink Consortium, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
9 changes: 7 additions & 2 deletions app/v1/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
let app = express();
const path = require('path');

Expand Down Expand Up @@ -79,10 +80,14 @@ function exposeRoutes () {
app.post('/applications/certificate', applications.updateAppCertificate);
app.get('/applications/groups', auth.validateAuth, applications.getFunctionalGroups);
app.put('/applications/groups', auth.validateAuth, applications.putFunctionalGroup);
// webengine app store
app.get('/applications/store', cors(), applications.getAppStore);
app.post('/webhook', applications.webhook); //webhook route
//begin policy table routes
app.post('/staging/policy', policy.postFromCoreStaging);
app.post('/production/policy', policy.postFromCoreProduction);
app.options('/staging/policy', cors())
app.options('/production/policy', cors())
app.post('/staging/policy', cors(), policy.postFromCoreStaging);
app.post('/production/policy', cors(), policy.postFromCoreProduction);
app.get('/policy/preview', policy.getPreview);
app.post('/policy/apps', policy.postAppPolicy);
//end policy table routes
Expand Down
37 changes: 37 additions & 0 deletions app/v1/applications/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,42 @@ function queryAndStoreCategories(callback) {
});
}

function getAppStore (req, res, next) {
// only let embedded apps through
let filterObj = {
approval_status: 'ACCEPTED',
platform: 'EMBEDDED',
};

if (req.query.uuid) { //filter by app uuid
filterObj.app_uuid = req.query.uuid;
}
if (req.query.transport_type) { //filter by transport type
filterObj.transport_type = req.query.transport_type;
}

let chosenFlow = helper.createAppInfoFlow('multiFilter', filterObj);

const finalFlow = flow([
chosenFlow,
helper.appStoreTransformation.bind(null, req.query.min_rpc_version, req.query.min_protocol_version),
], { method: 'waterfall' });

finalFlow(function (err, apps) {
if (err) {
app.locals.log.error(err)
return res.parcel.setStatus(500)
.setMessage("Internal Server Error")
.deliver();
}
return res.parcel.setStatus(200)
.setData({
applications: apps
})
.deliver();
})
}

module.exports = {
get: get,
actionPost: actionPost,
Expand All @@ -627,4 +663,5 @@ module.exports = {
getAppCertificate: getAppCertificate,
updateAppCertificate: updateAppCertificate,
checkAndUpdateCertificates: checkAndUpdateCertificates,
getAppStore: getAppStore,
};
81 changes: 81 additions & 0 deletions app/v1/applications/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,86 @@ function createFailedAppsCert(failedApp, next){
});
}

function appStoreTransformation (min_rpc_version, min_protocol_version, apps, next) {
// limit the information that's returned to the caller
if (min_rpc_version) {
apps = apps.filter(app => {
// filter out apps with a lower min rpc version than the query
const queryVersion = min_rpc_version.split('.');
const appVersion = app.min_rpc_version.split('.');
return versionCompare(appVersion, queryVersion)
});
}
if (min_protocol_version) {
apps = apps.filter(app => {
// filter out apps with a lower min rpc version than the query
const queryVersion = min_protocol_version.split('.');
const appVersion = app.min_protocol_version.split('.');
return versionCompare(appVersion, queryVersion)
});
}

const newApps = apps
.map(app => ({
name: app.name,
nicknames: app.display_names,
description: app.description,
policyAppID: app.uuid,
enabled: app.enabled,
transportType: app.cloud_transport_type,
hybridAppPreference: app.hybrid_app_preference,
icon_url: app.icon_url,
package: {
url: app.package_url,
size_compressed_bytes: app.size_compressed_bytes,
size_decompressed_bytes: app.size_decompressed_bytes,
}
}));
next(null, newApps);
}

// compares two versions with this syntax: [major, minor, patch]
// returns true if v1 is higher or equal to v2
// returns false otherwise
function versionCompare (v1, v2) {
if (v1[0] === undefined) {
v1[0] = 0;
}
if (v1[1] === undefined) {
v1[1] = 0;
}
if (v1[2] === undefined) {
v1[2] = 0;
}
if (v2[0] === undefined) {
v2[0] = 0;
}
if (v2[1] === undefined) {
v2[1] = 0;
}
if (v2[2] === undefined) {
v2[2] = 0;
}
// coerce to number
v1 = v1.map(Number);
v2 = v2.map(Number);

if (v1[0] > v2[0]) {
return true;
} else if (v1[0] === v2[0]) {
if (v1[1] > v2[1]) {
return true;
} else if (v1[1] === v2[1]) {
if (v1[2] > v2[2]) {
return true;
} else if (v1[2] === v2[2]) {
return true;
}
}
}
return false;
}

module.exports = {
validateActionPost: validateActionPost,
validateAutoPost: validateAutoPost,
Expand All @@ -358,4 +438,5 @@ module.exports = {
createAppInfoFlow: createAppInfoFlow,
storeApps: storeApps,
storeCategories: storeCategories,
appStoreTransformation: appStoreTransformation,
};
66 changes: 64 additions & 2 deletions app/v1/applications/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const sql = require('./sql.js');
const emails = require('../helpers/emails.js');
const certificates = require('../certificates/controller.js');
const certUtil = require('../helpers/certificates.js');
const webengineHandler = require('../../../customizable/webengine-bundle');
const Url = require('url').URL;

//takes SQL data and converts it into a response for the UI to consume
function constructFullAppObjs (res, next) {
Expand Down Expand Up @@ -91,6 +93,7 @@ function constructFullAppObjs (res, next) {
obj.display_names = [];
obj.permissions = [];
obj.services = arrayify(hashedServices, [appInfo.id]); //services should be an array
obj.description = appInfo.description;
}
}));

Expand Down Expand Up @@ -122,6 +125,7 @@ function constructFullAppObjs (res, next) {
for (let id in hashedApps) {
fullApps.push(hashedApps[id]);
}

next(null, fullApps);
}

Expand Down Expand Up @@ -156,6 +160,9 @@ function storeApp (notifyOEM, appObj, next) {
if (appObj.is_auto_approved_enabled) {
allInserts.push(sql.insertAppAutoApproval(appObj));
}
if (appObj.categories.length > 0) {
allInserts.push(sql.insertAppCategories(appObj.categories, app.id));
}

//generate app certificate if cert generation is enabled
if (certificates.openSSLEnabled) {
Expand Down Expand Up @@ -216,7 +223,62 @@ function storeApp (notifyOEM, appObj, next) {
flame.async.series(flame.map(allInserts, client.getOne, client), next);
}
},
//stage 3: sync with shaid
//stage 3: locales insert. this is a multi step process so it needs its own flow
function (res, next) {
if (!appObj.locales || appObj.locales.length === 0) {
return next(null, res); // no locales. skip
}

// attempt locale and tts chunks insert
const insertLocaleInfo = function (localeInfo, done) {
flame.async.waterfall([
client.getOne.bind(client, sql.insertAppLocale(localeInfo, storedApp.id)),
function (localeResult, next) {
// continue with inserting ttschunks after retreiving the returned id
// use the passed in locales
if (localeInfo.tts_chunks.length === 0) {
// no tts chunks to process. stop early
return next();
}
const query = sql.insertAppLocaleTtsChunks(localeInfo.tts_chunks, localeResult.id);
client.getOne(query, next);
}
], done);
}

flame.async.parallel(flame.map(appObj.locales, insertLocaleInfo), function (err) {
next(err, res);
});
},
//stage 4: call custom routine to get the byte size of the bundle at the package url if it exists
function (res, next) {
if (appObj.transport_type === 'webengine' && appObj.package_url) {
webengineHandler.handleBundle(appObj.package_url, function (err, data) {
if (err) {
return next(err);
}
if (!data) {
return next('No object returned for the webengine bundle for uuid ' + appObj.uuid);
}
if (!data.url) {
return next('No url property for the webengine bundle for uuid ' + appObj.uuid);
}
if (!data.size_compressed_bytes) {
return next('No size_compressed_bytes property for the webengine bundle for uuid ' + appObj.uuid);
}
if (!data.size_decompressed_bytes) {
return next('No size_decompressed_bytes property for the webengine bundle for uuid ' + appObj.uuid);
}
// store the returned results of the custom webengine bundle handler function
const query = sql.updateWebengineBundleInfo(storedApp.id, data);
client.getOne(query, next);
});
}
else {
next(null, res);
}
},
//stage 5: sync with shaid
function (res, next) {
if(!storedApp.version_id){
// skip sync with SHAID if no app version ID is present
Expand All @@ -227,7 +289,7 @@ function storeApp (notifyOEM, appObj, next) {
next(err, res);
});
},
//stage 4: notify OEM of pending app?
//stage 6: notify OEM of pending app?
function(res, next) {
if(!(
notifyOEM
Expand Down
77 changes: 75 additions & 2 deletions app/v1/applications/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ function getAppInfoFilter (filterObj) {
'app_info.approval_status': filterObj.approval_status
});
}
if(filterObj.platform){
statement.where({
'app_info.platform': filterObj.platform
});
}
if(filterObj.transport_type){
statement.where({
'app_info.transport_type': filterObj.transport_type
});
}
if(filterObj.get_blacklist){
statement.where(sql.isNotNull('app_oem_enablements.app_uuid'));
} else {
Expand Down Expand Up @@ -433,7 +443,15 @@ function insertAppInfo (obj) {
category_id: obj.category.id,
vendor_name: obj.vendor.name,
vendor_email: obj.vendor.email,
version_id: obj.version_id
version_id: obj.version_id,
min_rpc_version: obj.min_rpc_version,
min_protocol_version: obj.min_protocol_version,
developer_version: obj.developer_version,
package_url: obj.package_url,
entrypoint_path: obj.entrypoint_path,
icon_path: obj.icon_path,
transport_type: obj.transport_type,
description: obj.description,
};

if(obj.created_ts){
Expand Down Expand Up @@ -589,6 +607,44 @@ function insertAppServicePermission (obj) {
}).toString();
}

function insertAppCategories (objs, appId) {
if (objs.length === 0) {
return null;
}
const categoryInserts = objs.map(function (category) {
return {
app_id: appId,
category_id: category.id
}
});
return sql.insert('app_categories', categoryInserts).toString();
}

function insertAppLocale (obj, appId) {
return sql.insert('app_locale', {
app_id: appId,
locale: obj.locale.code,
name: obj.name,
vr_names: obj.vr_names,
})
.returning("id")
.toString();
}

function insertAppLocaleTtsChunks (objs, localeId) {
if (objs.length === 0) {
return null;
}
const localesInserts = objs.map(function (locale) {
return {
app_locale_id: localeId,
chunk_type: locale.chunk_type,
chunk_text: locale.chunk_text,
}
});
return sql.insert('app_locale_ttsname', localesInserts).toString();
}

function upsertCategories (categories) {
return categories.map(function (category) {
return sql.insert("categories", {
Expand Down Expand Up @@ -982,6 +1038,19 @@ function getBlacklistedAppFullUuids (uuids) {
return query.toString();
}

function updateWebengineBundleInfo (id, bundleInfo) {
return sql.update('app_info')
.set({
package_url: bundleInfo.url,
size_compressed_bytes: bundleInfo.size_compressed_bytes,
size_decompressed_bytes: bundleInfo.size_decompressed_bytes,
})
.where({
id: id
})
.toString();
}

module.exports = {
changeAppApprovalStatus: changeAppApprovalStatus,
deleteAutoApproval: deleteAutoApproval,
Expand Down Expand Up @@ -1073,5 +1142,9 @@ module.exports = {
upsertCategories: upsertCategories,
getAppFunctionalGroups: getAppFunctionalGroups,
insertAppFunctionalGroup: insertAppFunctionalGroup,
deleteAppFunctionalGroup: deleteAppFunctionalGroup
deleteAppFunctionalGroup: deleteAppFunctionalGroup,
insertAppCategories: insertAppCategories,
insertAppLocale: insertAppLocale,
insertAppLocaleTtsChunks: insertAppLocaleTtsChunks,
updateWebengineBundleInfo: updateWebengineBundleInfo
}
Loading

0 comments on commit 7eaa6db

Please sign in to comment.