feat(auth): migrate Application model from MongoDB to MySQL

- Add Sequelize migration creating the 'application' table
- Add Application Sequelize model with slugify, toJSONFor, toAuthJSON
- Rewrite passport-headerapikey strategy to use DB.Application
- Rewrite applications.routes.js to use Sequelize (findAll, count,
  build/save, destroy) instead of Mongoose
- Fix pre-existing bug: passport was querying { encryptedKey } but the
  stored field is named 'apikey'
- Add Application to MySQL models index and relationships
- Remove Application from Mongoose models index and delete the schema
This commit is contained in:
2026-04-26 18:26:58 +02:00
parent 097e11be1b
commit b3a31e4725
8 changed files with 228 additions and 148 deletions
-55
View File
@@ -1,55 +0,0 @@
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');
var slug = require('slug');
var ApplicationSchema = new mongoose.Schema({
apikey: String,
maskedkey: String,
slug: { type: String, lowercase: true, unique: true },
title: String,
description: String,
author: { type: String }
}, { timestamps: true, toJSON: { virtuals: true } });
ApplicationSchema.plugin(uniqueValidator, { message: 'is already taken' });
ApplicationSchema.pre('validate', function (next) {
if (!this.slug) {
this.slugify();
}
next();
});
ApplicationSchema.methods.slugify = function () {
this.slug = slug(this.title) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36);
};
ApplicationSchema.methods.toJSONFor = function (user) {
return {
maskedkey: this.maskedkey,
slug: this.slug,
title: this.title,
description: this.description,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
author: this.author && typeof this.author.toProfileJSONFor === 'function'
? this.author.toProfileJSONFor(user)
: (user && typeof user.toProfileJSONFor === 'function' ? user.toProfileJSONFor() : this.author ?? null)
};
};
ApplicationSchema.methods.toAuthJSON = function () {
return {
maskedkey: this.maskedkey,
slug: this.slug,
title: this.title,
description: this.description,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
author: this.author && typeof this.author.toJSONFor === 'function'
? this.author.toJSONFor()
: this.author ?? null
};
};
mongoose.model('Application', ApplicationSchema);
-1
View File
@@ -1,4 +1,3 @@
exports.Application = require('./Application');
exports.Aeronef = require('./Aeronef');
exports.Canopy = require('./Canopy');
exports.Dropzone = require('./Dropzone');
+103
View File
@@ -0,0 +1,103 @@
const { DataTypes, Model } = require('sequelize');
const { v4: uuidv4 } = require('uuid');
const slug = require('slug');
const sequelize = require('../../config/sequelize');
class Application extends Model {}
const ApplicationModel = () => {
Application.init(
{
id: {
type: DataTypes.STRING(36),
allowNull: false,
primaryKey: true
},
apikey: {
type: DataTypes.STRING(255),
allowNull: false
},
maskedkey: {
type: DataTypes.STRING(20),
allowNull: true
},
slug: {
type: DataTypes.STRING(255),
allowNull: false,
unique: 'slug'
},
title: {
type: DataTypes.STRING(255),
allowNull: false
},
description: {
type: DataTypes.TEXT,
allowNull: true
},
authorId: {
type: DataTypes.STRING(36),
allowNull: true
}
},
{
sequelize,
tableName: 'application',
timestamps: true,
indexes: [
{
name: 'PRIMARY',
unique: true,
using: 'BTREE',
fields: [{ name: 'id' }]
},
{
name: 'slug',
unique: true,
using: 'BTREE',
fields: [{ name: 'slug' }]
}
]
}
);
Application.beforeCreate((application) => {
application.id = uuidv4();
if (!application.slug) {
application.slugify();
}
application.slug = application.slug.toLowerCase();
});
Application.prototype.slugify = function () {
this.slug = slug(this.title) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36);
};
Application.prototype.toJSONFor = function (user) {
return {
maskedkey: this.maskedkey,
slug: this.slug,
title: this.title,
description: this.description,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
author: user ? user.toProfileJSONFor() : this.authorId ?? null
};
};
Application.prototype.toAuthJSON = function () {
return {
maskedkey: this.maskedkey,
slug: this.slug,
title: this.title,
description: this.description,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
author: this.authorId ?? null
};
};
return Application;
};
module.exports = ApplicationModel;
+1
View File
@@ -1,3 +1,4 @@
exports.Application = require('./Application');
exports.Article = require('./Article');
//exports.ArticleTag = require('./ArticleTag');
exports.Brand = require('./Brand');