ztechno_core 0.0.110 → 0.0.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/lib/crypto_service.d.ts +0 -23
- package/lib/crypto_service.js +0 -100
- package/lib/engine_base.d.ts +0 -11
- package/lib/engine_base.js +0 -9
- package/lib/express.d.ts +0 -1
- package/lib/express.js +0 -18
- package/lib/mail_service.d.ts +0 -85
- package/lib/mail_service.js +0 -156
- package/lib/orm/mail_blacklist_orm.d.ts +0 -22
- package/lib/orm/mail_blacklist_orm.js +0 -79
- package/lib/orm/orm.d.ts +0 -8
- package/lib/orm/orm.js +0 -26
- package/lib/scripts/docker-build.d.ts +0 -14
- package/lib/scripts/docker-build.js +0 -91
- package/lib/scripts/docker-publish.d.ts +0 -19
- package/lib/scripts/docker-publish.js +0 -114
- package/lib/scripts/docker-push.d.ts +0 -8
- package/lib/scripts/docker-push.js +0 -87
- package/lib/scripts/docker-update.d.ts +0 -27
- package/lib/scripts/docker-update.js +0 -207
- package/lib/scripts/encrypt.d.ts +0 -1
- package/lib/scripts/encrypt.js +0 -4
- package/lib/sql_service.d.ts +0 -123
- package/lib/sql_service.js +0 -234
- package/lib/translate_service.d.ts +0 -48
- package/lib/translate_service.js +0 -908
- package/lib/typings/crypto_types.d.ts +0 -4
- package/lib/typings/crypto_types.js +0 -2
- package/lib/typings/index.d.ts +0 -4
- package/lib/typings/index.js +0 -36
- package/lib/typings/mail_types.d.ts +0 -95
- package/lib/typings/mail_types.js +0 -2
- package/lib/typings/translate_types.d.ts +0 -69
- package/lib/typings/translate_types.js +0 -46
- package/lib/typings/user_types.d.ts +0 -41
- package/lib/typings/user_types.js +0 -2
- package/lib/user_service.d.ts +0 -80
- package/lib/user_service.js +0 -216
package/lib/typings/index.d.ts
DELETED
package/lib/typings/index.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
var __createBinding =
|
|
3
|
-
(this && this.__createBinding) ||
|
|
4
|
-
(Object.create
|
|
5
|
-
? function (o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () {
|
|
12
|
-
return m[k];
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
Object.defineProperty(o, k2, desc);
|
|
17
|
-
}
|
|
18
|
-
: function (o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
o[k2] = m[k];
|
|
21
|
-
});
|
|
22
|
-
var __exportStar =
|
|
23
|
-
(this && this.__exportStar) ||
|
|
24
|
-
function (m, exports) {
|
|
25
|
-
for (var p in m)
|
|
26
|
-
if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
29
|
-
// Crypto types
|
|
30
|
-
__exportStar(require('./crypto_types'), exports);
|
|
31
|
-
// Mail types
|
|
32
|
-
__exportStar(require('./mail_types'), exports);
|
|
33
|
-
// Translate types
|
|
34
|
-
__exportStar(require('./translate_types'), exports);
|
|
35
|
-
// User types
|
|
36
|
-
__exportStar(require('./user_types'), exports);
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
2
|
-
import { Attachment } from 'nodemailer/lib/mailer';
|
|
3
|
-
import { ZSQLService } from '../sql_service';
|
|
4
|
-
export type MailAttachment = Attachment;
|
|
5
|
-
interface OptionalOptions {
|
|
6
|
-
cacheDir?:
|
|
7
|
-
| string
|
|
8
|
-
| false
|
|
9
|
-
| undefined /** optional location for cached messages. If not set then caching is not used. */;
|
|
10
|
-
cacheTreshold?:
|
|
11
|
-
| number
|
|
12
|
-
| undefined /** optional size in bytes, if message is larger than this treshold it gets cached to disk (assuming cacheDir is set and writable). Defaults to 131072 (128 kB). */;
|
|
13
|
-
hashAlgo?: string | undefined /** optional algorithm for the body hash, defaults to ‘sha256’ */;
|
|
14
|
-
headerFieldNames?:
|
|
15
|
-
| string
|
|
16
|
-
| undefined /** an optional colon separated list of header keys to sign (eg. message-id:date:from:to...') */;
|
|
17
|
-
skipFields?:
|
|
18
|
-
| string
|
|
19
|
-
| undefined /** optional colon separated list of header keys not to sign. This is useful if you want to sign all the relevant keys but your provider changes some values, ie Message-ID and Date. In this case you should use 'message-id:date' to prevent signing these values. */;
|
|
20
|
-
}
|
|
21
|
-
interface SingleDKIMKeyOptions extends OptionalOptions {
|
|
22
|
-
domainName: string /** is the domain name to use in the signature */;
|
|
23
|
-
keySelector: string /** is the DKIM key selector */;
|
|
24
|
-
privateKey:
|
|
25
|
-
| string
|
|
26
|
-
| {
|
|
27
|
-
key: string;
|
|
28
|
-
passphrase: string;
|
|
29
|
-
} /** is the private key for the selector in PEM format */;
|
|
30
|
-
}
|
|
31
|
-
export type MailResponse = SMTPTransport.SentMessageInfo;
|
|
32
|
-
export type MailServiceOptions = {
|
|
33
|
-
auth: {
|
|
34
|
-
user: string;
|
|
35
|
-
pass: string;
|
|
36
|
-
};
|
|
37
|
-
mailSender: string;
|
|
38
|
-
dkim?: SingleDKIMKeyOptions;
|
|
39
|
-
sqlService: ZSQLService;
|
|
40
|
-
hashSalt?: string;
|
|
41
|
-
dirTemplate?: string;
|
|
42
|
-
baseInject?: {
|
|
43
|
-
logoSrc?: string;
|
|
44
|
-
baseUrl?: string;
|
|
45
|
-
title: string;
|
|
46
|
-
content: string;
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
export type MailOptionsBase = {
|
|
50
|
-
recipient: string;
|
|
51
|
-
subject: string;
|
|
52
|
-
from?: string;
|
|
53
|
-
priority?: 'high' | 'normal' | 'low';
|
|
54
|
-
dkim?: SingleDKIMKeyOptions;
|
|
55
|
-
attachments?: MailAttachment[];
|
|
56
|
-
};
|
|
57
|
-
export type MailOptionsText = MailOptionsBase & {
|
|
58
|
-
body: string;
|
|
59
|
-
};
|
|
60
|
-
export type MailOptionsHtml = MailOptionsBase & {
|
|
61
|
-
html: string;
|
|
62
|
-
};
|
|
63
|
-
export type MailOptions = MailOptionsBase & {
|
|
64
|
-
body?: string;
|
|
65
|
-
html?: string;
|
|
66
|
-
};
|
|
67
|
-
export type ZMailSendOptTemplate = MailOptionsBase & {
|
|
68
|
-
template: 'C:/example/template.html' | string;
|
|
69
|
-
inject: {
|
|
70
|
-
title: string;
|
|
71
|
-
content: string;
|
|
72
|
-
} & {
|
|
73
|
-
[key: string]: string | number;
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
export type ZMailSendOptAll = MailOptionsBase & {
|
|
77
|
-
body: string;
|
|
78
|
-
html: string;
|
|
79
|
-
template: 'C:/example/template.html' | string;
|
|
80
|
-
inject: {
|
|
81
|
-
title: string;
|
|
82
|
-
content: string;
|
|
83
|
-
} & {
|
|
84
|
-
[key: string]: string | number;
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
export type ZMailBlacklist = {
|
|
88
|
-
email: string;
|
|
89
|
-
hash?: string;
|
|
90
|
-
is_blacklisted: 0 | 1 | boolean;
|
|
91
|
-
updated_at: string;
|
|
92
|
-
created_at: string;
|
|
93
|
-
};
|
|
94
|
-
export type ZMailBlacklistSearch = Pick<ZMailBlacklist, 'email' | 'is_blacklisted'>;
|
|
95
|
-
export {};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { ZSQLService } from '../sql_service';
|
|
2
|
-
export type Dom = {} & Node;
|
|
3
|
-
export type Node = {
|
|
4
|
-
getAttribute: (attr: string) => string;
|
|
5
|
-
getElementsByTagName: (tag: string) => Node[];
|
|
6
|
-
getElementsByClassName: (cls: string) => Node[];
|
|
7
|
-
getElementById: (id: string) => Node;
|
|
8
|
-
getElementsByName: (name: string) => Node[];
|
|
9
|
-
nodeType: string;
|
|
10
|
-
nodeName: string;
|
|
11
|
-
childNodes: Node[];
|
|
12
|
-
firstChild: Node;
|
|
13
|
-
lastChild: Node;
|
|
14
|
-
parentNode: Node;
|
|
15
|
-
attributes: any[];
|
|
16
|
-
innerHTML: string;
|
|
17
|
-
outerHTML: string;
|
|
18
|
-
textContent: string;
|
|
19
|
-
text: string;
|
|
20
|
-
};
|
|
21
|
-
export type ZNodeText = {
|
|
22
|
-
text: string;
|
|
23
|
-
} & Node;
|
|
24
|
-
export type TranslateData = {
|
|
25
|
-
value: string;
|
|
26
|
-
meta?: {
|
|
27
|
-
prefix: string;
|
|
28
|
-
suffix: string;
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
export type dbTranslationRow = {
|
|
32
|
-
lang: string;
|
|
33
|
-
key: string;
|
|
34
|
-
value: string;
|
|
35
|
-
};
|
|
36
|
-
export type ATranslateLang = {
|
|
37
|
-
lang: string;
|
|
38
|
-
text: string;
|
|
39
|
-
};
|
|
40
|
-
export type TranslateServiceOptions = {
|
|
41
|
-
sqlService: ZSQLService;
|
|
42
|
-
googleApiKey: string;
|
|
43
|
-
languages?: ATranslateLang[];
|
|
44
|
-
defaultLang?: string;
|
|
45
|
-
sourceLang?: string;
|
|
46
|
-
surpressErrors?: boolean;
|
|
47
|
-
log?: (data: any, context: any) => any;
|
|
48
|
-
verbose?: (data: any, context: any) => any;
|
|
49
|
-
maxRetries?: number;
|
|
50
|
-
retryDelay?: number;
|
|
51
|
-
fallbackText?: string;
|
|
52
|
-
};
|
|
53
|
-
export declare class TranslateError extends Error {
|
|
54
|
-
code: string;
|
|
55
|
-
context?: any;
|
|
56
|
-
constructor(message: string, code: string, context?: any);
|
|
57
|
-
}
|
|
58
|
-
export declare class HtmlEntityError extends TranslateError {
|
|
59
|
-
constructor(code: string, text: string);
|
|
60
|
-
}
|
|
61
|
-
export declare class ApiTranslationError extends TranslateError {
|
|
62
|
-
constructor(originalError: any, text: string, lang: string);
|
|
63
|
-
}
|
|
64
|
-
export declare class DatabaseError extends TranslateError {
|
|
65
|
-
constructor(originalError: any, operation: string);
|
|
66
|
-
}
|
|
67
|
-
export declare class ValidationError extends TranslateError {
|
|
68
|
-
constructor(field: string, value: any);
|
|
69
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
-
exports.ValidationError =
|
|
4
|
-
exports.DatabaseError =
|
|
5
|
-
exports.ApiTranslationError =
|
|
6
|
-
exports.HtmlEntityError =
|
|
7
|
-
exports.TranslateError =
|
|
8
|
-
void 0;
|
|
9
|
-
// Custom error types for better error handling
|
|
10
|
-
class TranslateError extends Error {
|
|
11
|
-
constructor(message, code, context) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.code = code;
|
|
14
|
-
this.context = context;
|
|
15
|
-
this.name = 'TranslateError';
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.TranslateError = TranslateError;
|
|
19
|
-
class HtmlEntityError extends TranslateError {
|
|
20
|
-
constructor(code, text) {
|
|
21
|
-
super(`Cannot recognize character code="${code}" for text="${text}"`, 'HTML_ENTITY_ERROR', { code, text });
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.HtmlEntityError = HtmlEntityError;
|
|
25
|
-
class ApiTranslationError extends TranslateError {
|
|
26
|
-
constructor(originalError, text, lang) {
|
|
27
|
-
super(`Translation API failed for text="${text}" to language="${lang}"`, 'API_TRANSLATION_ERROR', {
|
|
28
|
-
originalError,
|
|
29
|
-
text,
|
|
30
|
-
lang,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
exports.ApiTranslationError = ApiTranslationError;
|
|
35
|
-
class DatabaseError extends TranslateError {
|
|
36
|
-
constructor(originalError, operation) {
|
|
37
|
-
super(`Database operation failed: ${operation}`, 'DATABASE_ERROR', { originalError, operation });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
exports.DatabaseError = DatabaseError;
|
|
41
|
-
class ValidationError extends TranslateError {
|
|
42
|
-
constructor(field, value) {
|
|
43
|
-
super(`Invalid ${field}: ${value}`, 'VALIDATION_ERROR', { field, value });
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
exports.ValidationError = ValidationError;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export type ZUserCore = {
|
|
2
|
-
user_id: number;
|
|
3
|
-
email: string;
|
|
4
|
-
session: string;
|
|
5
|
-
role: string | null;
|
|
6
|
-
admin: 0 | 1;
|
|
7
|
-
updated_at: any;
|
|
8
|
-
created_at: any;
|
|
9
|
-
};
|
|
10
|
-
export type ZUser = ZUserCore;
|
|
11
|
-
export interface ZUserExtended extends ZUserCore {
|
|
12
|
-
username?: string;
|
|
13
|
-
first_name?: string;
|
|
14
|
-
last_name?: string;
|
|
15
|
-
avatar_url?: string;
|
|
16
|
-
bio?: string;
|
|
17
|
-
is_active?: 0 | 1;
|
|
18
|
-
email_verified?: 0 | 1;
|
|
19
|
-
last_login?: any;
|
|
20
|
-
}
|
|
21
|
-
export type ZRequiredUserColumns = {
|
|
22
|
-
email: string;
|
|
23
|
-
role: string | null;
|
|
24
|
-
pass: string;
|
|
25
|
-
admin: 0 | 1;
|
|
26
|
-
};
|
|
27
|
-
export type ZRequiredUserColumnsExtended<T = {}> = ZRequiredUserColumns & Partial<T>;
|
|
28
|
-
export type ZUserCredentials = {
|
|
29
|
-
email: string;
|
|
30
|
-
pass: string;
|
|
31
|
-
};
|
|
32
|
-
export type ZUserSession = {
|
|
33
|
-
session: string;
|
|
34
|
-
};
|
|
35
|
-
export type ZUserTableConfig = {
|
|
36
|
-
tableName?: string;
|
|
37
|
-
customColumns?: {
|
|
38
|
-
[columnName: string]: string;
|
|
39
|
-
};
|
|
40
|
-
customIndexes?: string[];
|
|
41
|
-
};
|
package/lib/user_service.d.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { ZSQLService } from './sql_service';
|
|
2
|
-
import { ZRequiredUserColumns, ZUser, ZUserCore, ZUserSession, ZUserCredentials, ZUserTableConfig } from './typings';
|
|
3
|
-
/**
|
|
4
|
-
* Generic User Service that can be extended with custom user fields
|
|
5
|
-
* @template TUser - The user type (defaults to ZUser for backward compatibility)
|
|
6
|
-
* @template TUserCreate - The user creation type (defaults to ZRequiredUserColumns)
|
|
7
|
-
*/
|
|
8
|
-
export declare class ZUserService<
|
|
9
|
-
TUser extends ZUserCore = ZUser,
|
|
10
|
-
TUserCreate extends ZRequiredUserColumns = ZRequiredUserColumns,
|
|
11
|
-
> {
|
|
12
|
-
protected tableName: string;
|
|
13
|
-
protected sqlService: ZSQLService;
|
|
14
|
-
protected tableConfig: ZUserTableConfig;
|
|
15
|
-
private salt;
|
|
16
|
-
/**
|
|
17
|
-
* Creates a new ZUserService instance
|
|
18
|
-
* @param options - Configuration options including SQL service and optional table configuration
|
|
19
|
-
*/
|
|
20
|
-
constructor({ sqlService, tableConfig }: { sqlService: ZSQLService; tableConfig?: ZUserTableConfig });
|
|
21
|
-
/**
|
|
22
|
-
* Gets the base table columns definition
|
|
23
|
-
* @returns SQL column definitions for core user fields
|
|
24
|
-
* @protected
|
|
25
|
-
*/
|
|
26
|
-
protected getBaseTableColumns(): string;
|
|
27
|
-
/**
|
|
28
|
-
* Gets custom table columns if defined
|
|
29
|
-
* @returns SQL column definitions for custom fields
|
|
30
|
-
* @protected
|
|
31
|
-
*/
|
|
32
|
-
protected getCustomTableColumns(): string;
|
|
33
|
-
/**
|
|
34
|
-
* Gets base table indexes
|
|
35
|
-
* @returns SQL index definitions for core fields
|
|
36
|
-
* @protected
|
|
37
|
-
*/
|
|
38
|
-
protected getBaseTableIndexes(): string;
|
|
39
|
-
/**
|
|
40
|
-
* Gets custom table indexes if defined
|
|
41
|
-
* @returns SQL index definitions for custom fields
|
|
42
|
-
* @protected
|
|
43
|
-
*/
|
|
44
|
-
protected getCustomTableIndexes(): string;
|
|
45
|
-
protected checkTableExists(): Promise<boolean>;
|
|
46
|
-
checkTableHasAdmin(): Promise<boolean>;
|
|
47
|
-
protected createTable(): Promise<void>;
|
|
48
|
-
ensureTableExists(): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Registers a new user with extensible data
|
|
51
|
-
* @param userData - User data including core fields and any custom fields
|
|
52
|
-
* @returns Promise resolving to session information
|
|
53
|
-
*/
|
|
54
|
-
register(userData: TUserCreate): Promise<{
|
|
55
|
-
session: string;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* Gets all available columns for SELECT queries
|
|
59
|
-
* @returns Comma-separated list of column names
|
|
60
|
-
* @protected
|
|
61
|
-
*/
|
|
62
|
-
protected getSelectColumns(): string;
|
|
63
|
-
find(
|
|
64
|
-
opt:
|
|
65
|
-
| {
|
|
66
|
-
email: string;
|
|
67
|
-
}
|
|
68
|
-
| {
|
|
69
|
-
user_id: number;
|
|
70
|
-
},
|
|
71
|
-
): Promise<TUser | undefined>;
|
|
72
|
-
auth(opt: ZUserSession | ZUserCredentials): Promise<{
|
|
73
|
-
user?: TUser;
|
|
74
|
-
session?: string;
|
|
75
|
-
authenticated: boolean;
|
|
76
|
-
}>;
|
|
77
|
-
fetch(opt?: { limit?: number }): Promise<TUser[]>;
|
|
78
|
-
private genSession;
|
|
79
|
-
private hashPass;
|
|
80
|
-
}
|
package/lib/user_service.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
-
exports.ZUserService = void 0;
|
|
4
|
-
const crypto_service_1 = require('./crypto_service');
|
|
5
|
-
/**
|
|
6
|
-
* Generic User Service that can be extended with custom user fields
|
|
7
|
-
* @template TUser - The user type (defaults to ZUser for backward compatibility)
|
|
8
|
-
* @template TUserCreate - The user creation type (defaults to ZRequiredUserColumns)
|
|
9
|
-
*/
|
|
10
|
-
class ZUserService {
|
|
11
|
-
/**
|
|
12
|
-
* Creates a new ZUserService instance
|
|
13
|
-
* @param options - Configuration options including SQL service and optional table configuration
|
|
14
|
-
*/
|
|
15
|
-
constructor({ sqlService, tableConfig }) {
|
|
16
|
-
this.sqlService = sqlService;
|
|
17
|
-
this.tableConfig = tableConfig || {};
|
|
18
|
-
this.tableName = this.tableConfig.tableName || 'users';
|
|
19
|
-
this.salt = sqlService.database;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Gets the base table columns definition
|
|
23
|
-
* @returns SQL column definitions for core user fields
|
|
24
|
-
* @protected
|
|
25
|
-
*/
|
|
26
|
-
getBaseTableColumns() {
|
|
27
|
-
return `
|
|
28
|
-
\`user_id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
|
29
|
-
\`email\` varchar(255) NOT NULL,
|
|
30
|
-
\`role\` varchar(64) DEFAULT NULL,
|
|
31
|
-
\`pass\` varchar(512) NOT NULL,
|
|
32
|
-
\`session\` varchar(512) NOT NULL,
|
|
33
|
-
\`admin\` tinyint(1) NOT NULL DEFAULT 0,
|
|
34
|
-
\`updated_at\` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
35
|
-
\`created_at\` datetime NOT NULL DEFAULT current_timestamp()
|
|
36
|
-
`;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Gets custom table columns if defined
|
|
40
|
-
* @returns SQL column definitions for custom fields
|
|
41
|
-
* @protected
|
|
42
|
-
*/
|
|
43
|
-
getCustomTableColumns() {
|
|
44
|
-
if (!this.tableConfig.customColumns) return '';
|
|
45
|
-
return Object.entries(this.tableConfig.customColumns)
|
|
46
|
-
.map(([columnName, definition]) => `\`${columnName}\` ${definition}`)
|
|
47
|
-
.join(',\n ');
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Gets base table indexes
|
|
51
|
-
* @returns SQL index definitions for core fields
|
|
52
|
-
* @protected
|
|
53
|
-
*/
|
|
54
|
-
getBaseTableIndexes() {
|
|
55
|
-
return `
|
|
56
|
-
PRIMARY KEY (\`user_id\`),
|
|
57
|
-
UNIQUE KEY \`email_UNIQUE\` (\`email\`),
|
|
58
|
-
KEY \`email\` (\`email\`),
|
|
59
|
-
KEY \`role\` (\`role\`),
|
|
60
|
-
KEY \`admin\` (\`admin\`),
|
|
61
|
-
KEY \`created_at\` (\`created_at\`),
|
|
62
|
-
KEY \`updated_at\` (\`updated_at\`),
|
|
63
|
-
KEY \`session\` (\`session\`)
|
|
64
|
-
`;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Gets custom table indexes if defined
|
|
68
|
-
* @returns SQL index definitions for custom fields
|
|
69
|
-
* @protected
|
|
70
|
-
*/
|
|
71
|
-
getCustomTableIndexes() {
|
|
72
|
-
if (!this.tableConfig.customIndexes) return '';
|
|
73
|
-
return this.tableConfig.customIndexes
|
|
74
|
-
.map((index) => index.trim())
|
|
75
|
-
.filter((index) => index.length > 0)
|
|
76
|
-
.join(',\n ');
|
|
77
|
-
}
|
|
78
|
-
async checkTableExists() {
|
|
79
|
-
const res = await this.sqlService.query(`
|
|
80
|
-
SELECT ENGINE, VERSION, CREATE_TIME FROM information_schema.tables
|
|
81
|
-
WHERE table_schema = '${this.sqlService.database}' AND table_name = '${this.tableName}'
|
|
82
|
-
LIMIT 1
|
|
83
|
-
`);
|
|
84
|
-
return res.length > 0;
|
|
85
|
-
}
|
|
86
|
-
async checkTableHasAdmin() {
|
|
87
|
-
const res = await this.sqlService.query(`
|
|
88
|
-
SELECT user_id FROM \`${this.tableName}\` WHERE admin=1
|
|
89
|
-
`);
|
|
90
|
-
return res.length > 0;
|
|
91
|
-
}
|
|
92
|
-
async createTable() {
|
|
93
|
-
const baseColumns = this.getBaseTableColumns();
|
|
94
|
-
const customColumns = this.getCustomTableColumns();
|
|
95
|
-
const baseIndexes = this.getBaseTableIndexes();
|
|
96
|
-
const customIndexes = this.getCustomTableIndexes();
|
|
97
|
-
const allColumns = customColumns ? `${baseColumns},\n ${customColumns}` : baseColumns;
|
|
98
|
-
const allIndexes = customIndexes ? `${baseIndexes},\n ${customIndexes}` : baseIndexes;
|
|
99
|
-
await this.sqlService.query(`
|
|
100
|
-
CREATE TABLE \`${this.tableName}\` (
|
|
101
|
-
${allColumns},
|
|
102
|
-
${allIndexes}
|
|
103
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
|
104
|
-
`);
|
|
105
|
-
}
|
|
106
|
-
async ensureTableExists() {
|
|
107
|
-
const exists = await this.checkTableExists();
|
|
108
|
-
if (!exists) {
|
|
109
|
-
await this.createTable();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Registers a new user with extensible data
|
|
114
|
-
* @param userData - User data including core fields and any custom fields
|
|
115
|
-
* @returns Promise resolving to session information
|
|
116
|
-
*/
|
|
117
|
-
async register(userData) {
|
|
118
|
-
const session = this.genSession({ email: userData.email, pass: userData.pass });
|
|
119
|
-
// Build dynamic SQL for insertion
|
|
120
|
-
const coreFields = ['email', 'pass', 'session', 'role', 'admin'];
|
|
121
|
-
const customFields = Object.keys(userData).filter((key) => !coreFields.includes(key) && key !== 'pass');
|
|
122
|
-
const allFields = [...coreFields, ...customFields];
|
|
123
|
-
const placeholders = allFields.map(() => '?').join(', ');
|
|
124
|
-
const fieldNames = allFields.map((field) => `\`${field}\``).join(', ');
|
|
125
|
-
const values = allFields.map((field) => {
|
|
126
|
-
if (field === 'pass') return this.hashPass({ email: userData.email, pass: userData.pass });
|
|
127
|
-
if (field === 'session') return session;
|
|
128
|
-
return userData[field];
|
|
129
|
-
});
|
|
130
|
-
await this.sqlService.query(
|
|
131
|
-
`
|
|
132
|
-
INSERT INTO \`${this.tableName}\` (${fieldNames})
|
|
133
|
-
VALUES (${placeholders})
|
|
134
|
-
`,
|
|
135
|
-
values,
|
|
136
|
-
);
|
|
137
|
-
return { session };
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Gets all available columns for SELECT queries
|
|
141
|
-
* @returns Comma-separated list of column names
|
|
142
|
-
* @protected
|
|
143
|
-
*/
|
|
144
|
-
getSelectColumns() {
|
|
145
|
-
const baseColumns = ['user_id', 'email', 'session', 'role', 'admin', 'updated_at', 'created_at'];
|
|
146
|
-
const customColumns = this.tableConfig.customColumns ? Object.keys(this.tableConfig.customColumns) : [];
|
|
147
|
-
return [...baseColumns, ...customColumns].map((col) => `\`${col}\``).join(', ');
|
|
148
|
-
}
|
|
149
|
-
async find(opt) {
|
|
150
|
-
const selectColumns = this.getSelectColumns();
|
|
151
|
-
if (opt.email !== undefined) {
|
|
152
|
-
const rows = await this.sqlService.fetch({
|
|
153
|
-
Query: /*SQL*/ `
|
|
154
|
-
SELECT ${selectColumns} FROM \`${this.tableName}\`
|
|
155
|
-
WHERE email=:email
|
|
156
|
-
`,
|
|
157
|
-
Params: { email: opt.email },
|
|
158
|
-
});
|
|
159
|
-
return rows[0];
|
|
160
|
-
} else if (opt.user_id !== undefined) {
|
|
161
|
-
const rows = await this.sqlService.fetch({
|
|
162
|
-
Query: /*SQL*/ `
|
|
163
|
-
SELECT ${selectColumns} FROM \`${this.tableName}\`
|
|
164
|
-
WHERE user_id=:user_id
|
|
165
|
-
`,
|
|
166
|
-
Params: { user_id: opt.user_id },
|
|
167
|
-
});
|
|
168
|
-
return rows[0];
|
|
169
|
-
} else {
|
|
170
|
-
throw new Error(`Unexpected Input for ZUserService.find(${JSON.stringify(opt)})`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
async auth(opt) {
|
|
174
|
-
if (!opt.session && !opt.email && !opt.pass) {
|
|
175
|
-
return { authenticated: false };
|
|
176
|
-
}
|
|
177
|
-
const selectColumns = this.getSelectColumns();
|
|
178
|
-
const res = await (opt.session
|
|
179
|
-
? this.sqlService.fetch({
|
|
180
|
-
Query: /*SQL*/ `
|
|
181
|
-
SELECT ${selectColumns} FROM \`${this.tableName}\` WHERE session=?
|
|
182
|
-
`,
|
|
183
|
-
Params: [opt.session],
|
|
184
|
-
})
|
|
185
|
-
: this.sqlService.fetch({
|
|
186
|
-
Query: /*SQL*/ `
|
|
187
|
-
SELECT ${selectColumns} FROM \`${this.tableName}\` WHERE email=? AND pass=?
|
|
188
|
-
`,
|
|
189
|
-
Params: [opt.email, this.hashPass(opt)],
|
|
190
|
-
}));
|
|
191
|
-
return res.length === 0 ? { authenticated: false } : { user: res[0], session: res[0].session, authenticated: true };
|
|
192
|
-
}
|
|
193
|
-
async fetch(opt) {
|
|
194
|
-
const selectColumns = this.getSelectColumns();
|
|
195
|
-
const limit = opt?.limit || 100;
|
|
196
|
-
const rows = await this.sqlService.fetch(
|
|
197
|
-
`
|
|
198
|
-
SELECT ${selectColumns} FROM \`${this.tableName}\`
|
|
199
|
-
ORDER BY created_at DESC
|
|
200
|
-
LIMIT ?
|
|
201
|
-
`,
|
|
202
|
-
[limit],
|
|
203
|
-
);
|
|
204
|
-
return rows;
|
|
205
|
-
}
|
|
206
|
-
genSession({ email }) {
|
|
207
|
-
const salt = this.salt;
|
|
208
|
-
const data = email + Date.now() * Math.random();
|
|
209
|
-
return crypto_service_1.ZCryptoService.hash('sha256', data, { saltMode: 'simple', salt });
|
|
210
|
-
}
|
|
211
|
-
hashPass({ email, pass }) {
|
|
212
|
-
const salt = email + this.salt;
|
|
213
|
-
return crypto_service_1.ZCryptoService.hash('sha256', pass, { saltMode: 'simple', salt });
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
exports.ZUserService = ZUserService;
|