Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
ah-sequelize-plugin
Advanced tools
This plugin connects Sequelize and Actionhero. It handles running migrations and connecting your models. Under the hood, we use sequelize-typescript and Uzmug
3.0.0+
of this package are only compatible with Actionhero versions 24.0.0+
, sequelize v6+ and sequelize-typescript v2+. Node.js v10+ is required.2.0.0+
of this package are only compatible with Actionhero versions 21.0.0+
.1.0.0+
of this package are only compatible with Actionhero versions 18.0.0+
.For versions compatible with ActionHero versions prior to 21.0.0
, use version 1.x.x
.
For versions compatible with ActionHero versions prior to 18.0.0
, use version 0.9.x
.
npm install ah-sequelize-plugin --save
npm install sequelize@6 sequelize-typescript@2 --save
npm install @types/validator reflect-metadata --save
./src/config/plugins.ts
:import * as path from "path";
export const DEFAULT = {
plugins: () => {
return {
"ah-sequelize-plugin": {
path: path.join(process.cwd(), "node_modules", "ah-sequelize-plugin"),
},
};
},
};
experimentalDecorators
and emitDecoratorMetadata
to your Typescript tsconfig.json
file:{
"compilerOptions": {
"outDir": "./dist",
"allowJs": true,
"module": "commonjs",
"target": "es2018",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["./src/**/*"]
}
npm install mysql2 --save
npm install sqlite3 --save
npm install --save pg pg-hstore
npm install --save tedious
For additional information on supported databases visit the Sequelize Docs.
npm install --save-dev sequelize-cli
A ./src/config/sequelize.ts
will need to be created for your project. The example below will parse the Environment variable DATABASE_URL
for a postgres
database, however you can configure your connection in many ways. You can connect to DB pools, configure read/write splitting and more with Sequelize options. This configuration also enabled automigrate
, which means Actionhero will run your migrations for you at startup.
import { URL } from "url";
import { join } from "path";
export const DEFAULT = {
sequelize: (config) => {
let dialect = "postgres";
let host = process.env.DB_HOST || "127.0.0.1";
let port = process.env.DB_PORT || "5432";
let database = `app_${process.env.NODE_ENV || "development"}`;
let username =
process.env.DB_USER || process.env.CI ? "postgres" : undefined;
let password = process.env.DB_PASS || undefined;
// if your environment provides database information via a single JDBC-style URL like mysql://username:password@hostname:port/default_schema
const connectionURL =
process.env.DATABASE_URL || process.env.MYSQL_URL || process.env.PG_URL;
if (connectionURL) {
const parsed = new URL(connectionURL);
if (parsed.protocol) dialect = parsed.protocol.slice(0, -1);
if (parsed.username) username = parsed.username;
if (parsed.password) password = parsed.password;
if (parsed.hostname) host = parsed.hostname;
if (parsed.port) port = parsed.port;
if (parsed.pathname) database = parsed.pathname.substring(1);
}
if (dialect === "postgresql") dialect = "postgres";
return {
autoMigrate: true,
logging: false,
dialect: dialect,
port: parseInt(port),
database: database,
host: host,
username: username,
password: password,
models: [join(__dirname, "..", "models")],
migrations: [join(__dirname, "..", "migrations")],
// you can also pass "dialectOptions", for example if you need `{ssl: true}` for Postgres
};
},
};
// for the sequelize CLI tool
module.exports.development = DEFAULT.sequelize({
env: "development",
process: { env: "development" },
});
module.exports.staging = DEFAULT.sequelize({
env: "staging",
process: { env: "staging" },
});
module.exports.production = DEFAULT.sequelize({
env: "production",
process: { env: "production" },
});
If you installed the CLI in the last step, you'll want to do the following to finish setting it up:
Create a file .sequelizerc
in the root of your project. It should contain:
const path = require("path");
module.exports = {
config: path.resolve(".", "sequelize.js"),
"models-path": path.resolve("src", "models"),
"seeders-path": path.resolve("src", "seeders"),
"migrations-path": path.resolve("src", "migrations"),
};
This tells the sequelize-cli where to find your migration files, models, etc. The values here assume you are using the default configuration.
In the root folder create a file called sequelize.js
, and add the following contents
const sequelizeConfig = require("./dist/config/sequelize.js");
const sequelizeConfigEnv =
sequelizeConfig[process.env.NODE_ENV] || sequelizeConfig.DEFAULT;
module.exports = sequelizeConfigEnv.sequelize();
This initializes the config for the CLI to use.
Once you're done, the folder structure should look like so:
src/
models/
migrations/
.sequelizerc
sequelize.js
You can now use the CLI to create & run migrations:
npx sequelize-cli migration:generate --name migration-skeleton
The logging
configuration parameter accepts either a false
value, or a function which accepts a log value of type string
and a event level value of type string
(ex: console.log
, log
from Actionhero). If you are passing in a function for the logging parameter.
Thanks to sequelize-typescript
, we can have models with tagged parameters. The example below shows of how to use hooks, associations, and more. Further information can be found at https://github.com/RobinBuschmann/sequelize-typescript.
// from `src/models/Users.ts`
import * as bcrypt from "bcrypt";
import {
Model,
Table,
Column,
AllowNull,
IsEmail,
BeforeCreate,
HasMany,
} from "sequelize-typescript";
import * as uuid from "uuid/v4";
import { Post } from "./Post";
@Table({ tableName: "users", paranoid: true })
export class User extends Model<User> {
saltRounds = 10;
@Column({ primaryKey: true })
guid: string;
@AllowNull(false)
@Column
firstName: string;
@AllowNull(false)
@Column
lastName: string;
@AllowNull(false)
@IsEmail
@Column
email: string;
@Column
passwordHash: string;
@HasMany(() => Post)
posts: Post[];
@BeforeCreate
static generateGuid(instance) {
if (!instance.guid) {
instance.guid = uuid();
}
}
async updatePassword(password: string) {
this.passwordHash = await bcrypt.hash(password, this.saltRounds);
await this.save();
}
async checkPassword(password: string) {
if (!this.passwordHash) {
throw new Error("password not set for this team member");
}
const match = await bcrypt.compare(password, this.passwordHash);
return match;
}
}
You can then use these models in your Actions, Tasks, etc, by simply requiring them.
// from actions/user.ts
import { Action } from "actionhero";
import { User } from "./../models/User";
export class UserCreate extends Action {
constructor() {
super();
this.name = "user:create";
this.description = "create a new user";
this.outputExample = {};
this.inputs = {
firstName: { required: true },
lastName: { required: true },
password: { required: true },
email: { required: true },
};
}
async run({ params, response }) {
const user = new User({
firstName: params.firstName,
lastName: params.lastName,
email: params.email,
});
await user.save();
await user.updatePassword(params.password);
response.userGuid = user.guid;
}
}
This plugin does not condone the use of Sequelize.sync()
in favor of migrations. Keep you migrations in ./migrations
and use the sequelize-cli to execute them.
An example migration to create a users
table would look like:
// from ./migrations/0000001-createUsersTable.ts
module.exports = {
up: async function (migration, DataTypes) {
await migration.createTable(
"users",
{
guid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
firstName: {
type: DataTypes.STRING(191),
allowNull: false,
},
lastName: {
type: DataTypes.STRING(191),
allowNull: false,
},
email: {
type: DataTypes.STRING(191),
allowNull: false,
},
passwordHash: {
type: DataTypes.TEXT,
allowNull: true,
},
lastLoginAt: {
type: DataTypes.DATE,
allowNull: true,
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
deletedAt: DataTypes.DATE,
},
{
charset: "utf8mb4",
}
);
await migration.addIndex("users", ["email"], {
unique: true,
fields: "email",
});
},
down: async function (migration) {
await migration.dropTable("users");
},
};
You can use the sequelize-cli to create and execute migrations.
By default, ah-sequelize-plugin
will automatically execute any pending migrations when Actionhero starts up. You can disable this behavior by adding autoMigrate: false
to your sequelize config.
As of version 2.0.0
, we have removed support for fixtures from this plugin. If you need to load data into your application consider an Initializer in your project.
FAQs
Use Sequelize in ActionHero
The npm package ah-sequelize-plugin receives a total of 1,228 weekly downloads. As such, ah-sequelize-plugin popularity was classified as popular.
We found that ah-sequelize-plugin demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.