Add multi-user backend infrastructure: User model, management service and API

Co-authored-by: whyour <22700758+whyour@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-11-07 16:24:00 +00:00
co-authored by whyour
parent 4758400df6
commit db93ca9aa9
11 changed files with 356 additions and 16 deletions
+3
View File
@@ -21,6 +21,7 @@ export class Crontab {
extra_schedules?: Array<{ schedule: string }>;
task_before?: string;
task_after?: string;
userId?: number;
constructor(options: Crontab) {
this.name = options.name;
@@ -45,6 +46,7 @@ export class Crontab {
this.extra_schedules = options.extra_schedules;
this.task_before = options.task_before;
this.task_after = options.task_after;
this.userId = options.userId;
}
}
@@ -84,4 +86,5 @@ export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
extra_schedules: DataTypes.JSON,
task_before: DataTypes.STRING,
task_after: DataTypes.STRING,
userId: { type: DataTypes.NUMBER, allowNull: true },
});
+3
View File
@@ -9,6 +9,7 @@ export class Dependence {
name: string;
log?: string[];
remark?: string;
userId?: number;
constructor(options: Dependence) {
this.id = options.id;
@@ -21,6 +22,7 @@ export class Dependence {
this.name = options.name.trim();
this.log = options.log || [];
this.remark = options.remark || '';
this.userId = options.userId;
}
}
@@ -59,5 +61,6 @@ export const DependenceModel = sequelize.define<DependenceInstance>(
status: DataTypes.NUMBER,
log: DataTypes.JSON,
remark: DataTypes.STRING,
userId: { type: DataTypes.NUMBER, allowNull: true },
},
);
+3
View File
@@ -9,6 +9,7 @@ export class Env {
position?: number;
name?: string;
remarks?: string;
userId?: number;
constructor(options: Env) {
this.value = options.value;
@@ -21,6 +22,7 @@ export class Env {
this.position = options.position;
this.name = options.name;
this.remarks = options.remarks || '';
this.userId = options.userId;
}
}
@@ -42,4 +44,5 @@ export const EnvModel = sequelize.define<EnvInstance>('Env', {
position: DataTypes.NUMBER,
name: { type: DataTypes.STRING, unique: 'compositeIndex' },
remarks: DataTypes.STRING,
userId: { type: DataTypes.NUMBER, allowNull: true },
});
+3
View File
@@ -31,6 +31,7 @@ export class Subscription {
proxy?: string;
autoAddCron?: 1 | 0;
autoDelCron?: 1 | 0;
userId?: number;
constructor(options: Subscription) {
this.id = options.id;
@@ -60,6 +61,7 @@ export class Subscription {
this.proxy = options.proxy;
this.autoAddCron = options.autoAddCron ? 1 : 0;
this.autoDelCron = options.autoDelCron ? 1 : 0;
this.userId = options.userId;
}
}
@@ -111,5 +113,6 @@ export const SubscriptionModel = sequelize.define<SubscriptionInstance>(
proxy: { type: DataTypes.STRING, allowNull: true },
autoAddCron: { type: DataTypes.NUMBER, allowNull: true },
autoDelCron: { type: DataTypes.NUMBER, allowNull: true },
userId: { type: DataTypes.NUMBER, allowNull: true },
},
);
+56
View File
@@ -0,0 +1,56 @@
import { sequelize } from '.';
import { DataTypes, Model } from 'sequelize';
export class User {
id?: number;
username: string;
password: string;
role: UserRole;
status: UserStatus;
createdAt?: Date;
updatedAt?: Date;
constructor(options: User) {
this.id = options.id;
this.username = options.username;
this.password = options.password;
this.role = options.role || UserRole.user;
this.status =
typeof options.status === 'number' && UserStatus[options.status]
? options.status
: UserStatus.active;
this.createdAt = options.createdAt;
this.updatedAt = options.updatedAt;
}
}
export enum UserRole {
'admin' = 0,
'user' = 1,
}
export enum UserStatus {
'active' = 0,
'disabled' = 1,
}
export interface UserInstance extends Model<User, User>, User {}
export const UserModel = sequelize.define<UserInstance>('User', {
username: {
type: DataTypes.STRING,
unique: true,
allowNull: false,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
role: {
type: DataTypes.NUMBER,
defaultValue: UserRole.user,
},
status: {
type: DataTypes.NUMBER,
defaultValue: UserStatus.active,
},
});