spee.ch/server/models/claim.js

446 lines
11 KiB
JavaScript
Raw Normal View History

const logger = require('winston');
const returnShortId = require('./utils/returnShortId.js');
const isApprovedChannel = require('../../utils/isApprovedChannel');
2019-01-26 01:37:07 +01:00
const {
assetDefaults: { thumbnail: defaultThumbnail },
details: { host },
} = require('@config/siteConfig');
const {
publishing: { serveOnlyApproved, approvedChannels },
} = require('@config/siteConfig');
const NO_CLAIM = 'NO_CLAIM';
2019-01-26 01:37:07 +01:00
function determineFileExtensionFromContentType(contentType) {
switch (contentType) {
case 'image/jpeg':
case 'image/jpg':
return 'jpg';
case 'image/png':
return 'png';
case 'image/gif':
return 'gif';
case 'video/mp4':
return 'mp4';
2019-01-26 01:37:07 +01:00
case 'image/svg+xml':
return 'svg';
default:
logger.debug('setting unknown file type as file extension jpg');
return 'jpg';
}
}
2019-01-26 01:37:07 +01:00
function determineThumbnail(storedThumbnail, defaultThumbnail) {
2017-12-21 19:50:47 +01:00
if (storedThumbnail === '') {
return defaultThumbnail;
}
2017-12-21 19:50:47 +01:00
return storedThumbnail;
}
2019-01-26 01:37:07 +01:00
function prepareClaimData(claim) {
2017-12-07 00:15:21 +01:00
// logger.debug('preparing claim data based on resolved data:', claim);
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
2017-12-07 00:15:21 +01:00
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
claim['host'] = host;
2017-12-07 00:15:21 +01:00
return claim;
}
2019-01-26 01:37:07 +01:00
function isLongClaimId(claimId) {
return claimId && claimId.length === 40;
}
2019-01-26 01:37:07 +01:00
function isShortClaimId(claimId) {
return claimId && claimId.length < 40;
}
module.exports = (sequelize, { STRING, BOOLEAN, INTEGER, TEXT, DECIMAL }) => {
const Claim = sequelize.define(
'Claim',
{
address: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
amount: {
2019-01-26 01:37:07 +01:00
type: DECIMAL(19, 8),
2017-08-15 01:16:32 +02:00
default: null,
},
claimId: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
claimSequence: {
2019-01-26 01:37:07 +01:00
type: INTEGER,
2017-08-15 01:16:32 +02:00
default: null,
},
decodedClaim: {
2019-01-26 01:37:07 +01:00
type: BOOLEAN,
2017-08-15 01:16:32 +02:00
default: null,
},
depth: {
2019-01-26 01:37:07 +01:00
type: INTEGER,
2017-08-15 01:16:32 +02:00
default: null,
},
effectiveAmount: {
2019-01-26 01:37:07 +01:00
type: DECIMAL(19, 8),
2017-08-15 01:16:32 +02:00
default: null,
},
hasSignature: {
2019-01-26 01:37:07 +01:00
type: BOOLEAN,
2017-08-15 01:16:32 +02:00
default: null,
},
height: {
2019-01-26 01:37:07 +01:00
type: INTEGER,
2017-08-15 01:16:32 +02:00
default: null,
},
hex: {
2019-01-26 01:37:07 +01:00
type: TEXT('long'),
2017-08-15 01:16:32 +02:00
default: null,
},
name: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
nout: {
2019-01-26 01:37:07 +01:00
type: INTEGER,
2017-08-15 01:16:32 +02:00
default: null,
},
txid: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
validAtHeight: {
2019-01-26 01:37:07 +01:00
type: INTEGER,
default: null,
},
outpoint: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
claimType: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 01:16:32 +02:00
default: null,
},
2017-08-15 22:48:42 +02:00
certificateId: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 22:48:42 +02:00
default: null,
},
author: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
description: {
2019-01-26 01:37:07 +01:00
type: TEXT('long'),
default: null,
},
language: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
2017-08-15 22:48:42 +02:00
},
license: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-08-15 22:48:42 +02:00
default: null,
},
licenseUrl: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
nsfw: {
2019-01-26 01:37:07 +01:00
type: BOOLEAN,
default: null,
},
preview: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
thumbnail: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
title: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
metadataVersion: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
contentType: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
source: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
sourceType: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
sourceVersion: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
streamVersion: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
valueVersion: {
2019-01-26 01:37:07 +01:00
type: STRING,
default: null,
},
2017-10-26 17:31:38 +02:00
channelName: {
2019-01-26 01:37:07 +01:00
type: STRING,
2017-10-26 17:31:38 +02:00
allowNull: true,
2019-01-26 01:37:07 +01:00
default: null,
2017-10-26 17:31:38 +02:00
},
},
{
freezeTableName: true,
}
);
2017-09-15 23:41:47 +02:00
Claim.associate = db => {
Claim.belongsTo(db.File, {
foreignKey: {
allowNull: true,
},
});
};
2019-01-26 01:37:07 +01:00
Claim.getShortClaimIdFromLongClaimId = function(claimId, claimName) {
logger.debug(`Claim.getShortClaimIdFromLongClaimId for ${claimName}#${claimId}`);
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: { name: claimName },
order: [['height', 'ASC']],
})
.then(result => {
switch (result.length) {
case 0:
2017-11-14 23:52:20 +01:00
throw new Error('No claim(s) found with that claim name');
default:
2017-11-04 01:10:08 +01:00
resolve(returnShortId(result, claimId));
}
})
.catch(error => {
reject(error);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.getAllChannelClaims = function(channelClaimId) {
2017-12-06 00:11:16 +01:00
logger.debug(`Claim.getAllChannelClaims for ${channelClaimId}`);
2017-10-31 19:54:33 +01:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: { certificateId: channelClaimId },
order: [['height', 'DESC']],
raw: true, // returns an array of only data, not an array of instances
})
.then(channelClaimsArray => {
switch (channelClaimsArray.length) {
2017-10-31 19:54:33 +01:00
case 0:
return resolve(null);
default:
channelClaimsArray.forEach(claim => {
claim['fileExt'] = determineFileExtensionFromContentType(claim.contentType);
claim['thumbnail'] = determineThumbnail(claim.thumbnail, defaultThumbnail);
return claim;
});
return resolve(channelClaimsArray);
2017-10-31 19:54:33 +01:00
}
})
.catch(error => {
reject(error);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.getClaimIdByLongChannelId = function(channelClaimId, claimName) {
2017-12-06 00:11:16 +01:00
logger.debug(`finding claim id for claim ${claimName} from channel ${channelClaimId}`);
2017-10-31 23:28:11 +01:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: { name: claimName, certificateId: channelClaimId },
order: [['id', 'ASC']],
})
2017-10-31 23:28:11 +01:00
.then(result => {
switch (result.length) {
case 0:
return reject(NO_CLAIM);
2017-10-31 23:28:11 +01:00
case 1:
return resolve(result[0].claimId);
default:
2019-01-26 01:37:07 +01:00
logger.warn(
`${result.length} records found for "${claimName}" in channel "${channelClaimId}"`
);
2017-10-31 23:28:11 +01:00
return resolve(result[0].claimId);
}
})
.catch(error => {
reject(error);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.validateLongClaimId = function(name, claimId) {
return new Promise((resolve, reject) => {
this.findOne({
where: {
name,
claimId,
},
})
.then(result => {
if (!result) {
return reject(NO_CLAIM);
}
resolve(claimId);
})
.catch(error => {
logger.error(error);
reject(NO_CLAIM);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.getLongClaimIdFromShortClaimId = function(name, shortId) {
2017-11-01 00:00:12 +01:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: {
name,
claimId: {
[sequelize.Op.like]: `${shortId}%`,
},
},
order: [['height', 'ASC']],
})
2017-11-01 00:00:12 +01:00
.then(result => {
switch (result.length) {
case 0:
return reject(NO_CLAIM);
default:
2017-11-01 00:00:12 +01:00
return resolve(result[0].claimId);
}
})
.catch(error => {
logger.error(error);
reject(NO_CLAIM);
2017-11-01 00:00:12 +01:00
});
});
};
2019-01-26 01:37:07 +01:00
Claim.getTopFreeClaimIdByClaimName = function(name) {
2017-11-01 00:00:12 +01:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: { name },
order: [['effectiveAmount', 'DESC'], ['height', 'ASC']],
})
2017-11-01 00:00:12 +01:00
.then(result => {
switch (result.length) {
case 0:
return reject(NO_CLAIM);
2017-11-01 00:00:12 +01:00
default:
return resolve(result[0].dataValues.claimId);
2017-11-01 00:00:12 +01:00
}
})
.catch(error => {
logger.error(error);
reject(NO_CLAIM);
});
2017-11-21 21:53:43 +01:00
});
};
2019-01-26 01:37:07 +01:00
Claim.getLongClaimId = function(claimName, claimId) {
logger.debug(`getLongClaimId(${claimName}, ${claimId})`);
if (isLongClaimId(claimId)) {
2017-11-21 21:53:43 +01:00
return this.validateLongClaimId(claimName, claimId);
} else if (isShortClaimId(claimId)) {
return this.getLongClaimIdFromShortClaimId(claimName, claimId);
2017-11-01 00:00:12 +01:00
} else {
return this.getTopFreeClaimIdByClaimName(claimName);
2017-11-01 00:00:12 +01:00
}
};
2019-01-26 01:37:07 +01:00
Claim.fetchClaim = function(name, claimId) {
2018-01-31 00:32:42 +01:00
logger.debug(`Claim.resolveClaim: ${name} ${claimId}`);
2017-11-01 00:44:32 +01:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.findAll({
where: { name, claimId },
})
.then(claimArray => {
switch (claimArray.length) {
case 0:
return resolve(null);
2017-11-01 00:44:32 +01:00
case 1:
return resolve(prepareClaimData(claimArray[0].dataValues));
2017-11-01 00:44:32 +01:00
default:
2018-08-01 19:25:35 +02:00
logger.warn(`more than one record matches ${name}#${claimId} in db.Claim`);
return resolve(prepareClaimData(claimArray[0].dataValues));
2017-11-01 00:44:32 +01:00
}
})
.catch(error => {
reject(error);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.resolveClaim = function(name, claimId) {
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
this.fetchClaim(name, claimId)
.then(claim => {
logger.info('resolveClaim claims:', claim);
2019-01-26 01:37:07 +01:00
if (
serveOnlyApproved &&
!isApprovedChannel({ longId: claim.certificateId }, approvedChannels)
) {
throw new Error('This content is unavailable');
}
return resolve(claim);
})
.catch(error => {
reject(error);
});
});
};
2019-01-26 01:37:07 +01:00
Claim.getOutpoint = function(name, claimId) {
logger.debug(`finding outpoint for ${name}#${claimId}`);
2019-01-26 01:37:07 +01:00
return this.findAll({
where: { name, claimId },
attributes: ['outpoint'],
})
.then(result => {
logger.debug('outpoint result');
switch (result.length) {
case 0:
throw new Error(`no record found for ${name}#${claimId}`);
case 1:
return result[0].dataValues.outpoint;
default:
2018-08-01 19:25:35 +02:00
logger.warn(`more than one record matches ${name}#${claimId} in db.Claim`);
return result[0].dataValues.outpoint;
}
})
.catch(error => {
throw error;
});
};
2019-01-26 01:37:07 +01:00
Claim.getCurrentHeight = function() {
2018-08-15 20:30:08 +02:00
return new Promise((resolve, reject) => {
2019-01-26 01:37:07 +01:00
return this.max('height')
2018-08-15 20:30:08 +02:00
.then(result => {
if (result) {
return resolve(result);
}
return resolve(100000);
})
.catch(error => {
return reject(error);
});
});
};
return Claim;
};