chore(xo-server): remove Model wrapping
This commit is contained in:
parent
9ef2c7da4c
commit
8a71f84733
@ -1,7 +1,6 @@
|
||||
import Model from './model.mjs'
|
||||
import { BaseError } from 'make-error'
|
||||
import { EventEmitter } from 'events'
|
||||
import { isObject, map } from './utils.mjs'
|
||||
import { isObject } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
@ -14,34 +13,16 @@ export class ModelAlreadyExists extends BaseError {
|
||||
// ===================================================================
|
||||
|
||||
export default class Collection extends EventEmitter {
|
||||
// Default value for Model.
|
||||
get Model() {
|
||||
return Model
|
||||
}
|
||||
|
||||
// Make this property writable.
|
||||
set Model(Model) {
|
||||
Object.defineProperty(this, 'Model', {
|
||||
configurable: true,
|
||||
enumerale: true,
|
||||
value: Model,
|
||||
writable: true,
|
||||
})
|
||||
}
|
||||
|
||||
async add(models, opts) {
|
||||
const array = Array.isArray(models)
|
||||
if (!array) {
|
||||
models = [models]
|
||||
}
|
||||
|
||||
const { Model } = this
|
||||
map(models, model => (model instanceof Model ? model.properties : model), models)
|
||||
|
||||
models = await this._add(models, opts)
|
||||
this.emit('add', models)
|
||||
|
||||
return array ? models : new this.Model(models[0])
|
||||
return array ? models : models[0]
|
||||
}
|
||||
|
||||
async first(properties) {
|
||||
@ -49,8 +30,7 @@ export default class Collection extends EventEmitter {
|
||||
properties = properties !== undefined ? { id: properties } : {}
|
||||
}
|
||||
|
||||
const model = await this._first(properties)
|
||||
return model && new this.Model(model)
|
||||
return await this._first(properties)
|
||||
}
|
||||
|
||||
async get(properties) {
|
||||
@ -93,33 +73,18 @@ export default class Collection extends EventEmitter {
|
||||
models = [models]
|
||||
}
|
||||
|
||||
const { Model } = this
|
||||
map(
|
||||
models,
|
||||
model => {
|
||||
if (!(model instanceof Model)) {
|
||||
// TODO: Problems, we may be mixing in some default
|
||||
// properties which will overwrite existing ones.
|
||||
model = new Model(model)
|
||||
}
|
||||
|
||||
const id = model.get('id')
|
||||
|
||||
// Missing models should be added not updated.
|
||||
if (id === undefined) {
|
||||
// FIXME: should not throw an exception but return a rejected promise.
|
||||
throw new Error('a model without an id cannot be updated')
|
||||
}
|
||||
|
||||
return model.properties
|
||||
},
|
||||
models
|
||||
)
|
||||
models.forEach(model => {
|
||||
// Missing models should be added not updated.
|
||||
if (model.id === undefined) {
|
||||
// FIXME: should not throw an exception but return a rejected promise.
|
||||
throw new Error('a model without an id cannot be updated')
|
||||
}
|
||||
})
|
||||
|
||||
models = await this._update(models)
|
||||
this.emit('update', models)
|
||||
|
||||
return array ? models : new this.Model(models[0])
|
||||
return array ? models : models[0]
|
||||
}
|
||||
|
||||
// Methods to override in implementations.
|
||||
|
@ -1,61 +0,0 @@
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
import { forEach, isEmpty } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Model extends EventEmitter {
|
||||
constructor(properties) {
|
||||
super()
|
||||
|
||||
this.properties = { ...this.default }
|
||||
|
||||
if (properties) {
|
||||
this.set(properties)
|
||||
}
|
||||
}
|
||||
|
||||
// Get a property.
|
||||
get(name, def) {
|
||||
const value = this.properties[name]
|
||||
return value !== undefined ? value : def
|
||||
}
|
||||
|
||||
// Check whether a property exists.
|
||||
has(name) {
|
||||
return this.properties[name] !== undefined
|
||||
}
|
||||
|
||||
// Set properties.
|
||||
set(properties, value) {
|
||||
// This method can also be used with two arguments to set a single
|
||||
// property.
|
||||
if (typeof properties === 'string') {
|
||||
properties = { [properties]: value }
|
||||
}
|
||||
|
||||
const previous = {}
|
||||
|
||||
forEach(properties, (value, name) => {
|
||||
const prev = this.properties[name]
|
||||
|
||||
if (value !== prev) {
|
||||
previous[name] = prev
|
||||
|
||||
if (value === undefined) {
|
||||
delete this.properties[name]
|
||||
} else {
|
||||
this.properties[name] = value
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!isEmpty(previous)) {
|
||||
this.emit('change', previous)
|
||||
|
||||
forEach(previous, (value, name) => {
|
||||
this.emit('change:' + name, value)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
import { forEach, multiKeyHash } from '../utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
@ -10,27 +9,16 @@ const DEFAULT_ACTION = 'admin'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Acl extends Model {}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export class Acls extends Collection {
|
||||
get Model() {
|
||||
return Acl
|
||||
}
|
||||
|
||||
create(subject, object, action) {
|
||||
return multiKeyHash(subject, object, action)
|
||||
.then(
|
||||
hash =>
|
||||
new Acl({
|
||||
id: hash,
|
||||
subject,
|
||||
object,
|
||||
action,
|
||||
})
|
||||
)
|
||||
.then(acl => this.add(acl))
|
||||
return multiKeyHash(subject, object, action).then(hash =>
|
||||
this.add({
|
||||
id: hash,
|
||||
subject,
|
||||
object,
|
||||
action,
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
delete(subject, object, action) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import isEmpty from 'lodash/isEmpty.js'
|
||||
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
|
||||
import { forEach } from '../utils.mjs'
|
||||
|
||||
@ -9,17 +8,9 @@ import { parseProp } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Group extends Model {}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export class Groups extends Collection {
|
||||
get Model() {
|
||||
return Group
|
||||
}
|
||||
|
||||
create(name, provider, providerGroupId) {
|
||||
return this.add(new Group({ name, provider, providerGroupId }))
|
||||
return this.add({ name, provider, providerGroupId })
|
||||
}
|
||||
|
||||
async save(group) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
import { createLogger } from '@xen-orchestra/log'
|
||||
import { forEach } from '../utils.mjs'
|
||||
|
||||
@ -7,15 +6,7 @@ const log = createLogger('xo:plugin-metadata')
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class PluginMetadata extends Model {}
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export class PluginsMetadata extends Collection {
|
||||
get Model() {
|
||||
return PluginMetadata
|
||||
}
|
||||
|
||||
async save({ id, autoload, configuration }) {
|
||||
return /* await */ this.update({
|
||||
id,
|
||||
@ -31,7 +22,7 @@ export class PluginsMetadata extends Collection {
|
||||
}
|
||||
|
||||
return /* await */ this.save({
|
||||
...pluginMetadata.properties,
|
||||
...pluginMetadata,
|
||||
...data,
|
||||
})
|
||||
}
|
||||
|
@ -1,18 +1,11 @@
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
import { forEach, serializeError } from '../utils.mjs'
|
||||
|
||||
import { parseProp } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Remote extends Model {}
|
||||
|
||||
export class Remotes extends Collection {
|
||||
get Model() {
|
||||
return Remote
|
||||
}
|
||||
|
||||
async get(properties) {
|
||||
const remotes = await super.get(properties)
|
||||
forEach(remotes, remote => {
|
||||
|
@ -1,20 +1,11 @@
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
import { forEach, serializeError } from '../utils.mjs'
|
||||
|
||||
import { parseProp } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Server extends Model {}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export class Servers extends Collection {
|
||||
get Model() {
|
||||
return Server
|
||||
}
|
||||
|
||||
async create(params) {
|
||||
const { host } = params
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class Token extends Model {}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export class Tokens extends Collection {}
|
||||
|
@ -1,20 +1,11 @@
|
||||
import isEmpty from 'lodash/isEmpty.js'
|
||||
|
||||
import Collection from '../collection/redis.mjs'
|
||||
import Model from '../model.mjs'
|
||||
|
||||
import { parseProp } from './utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
|
||||
export default class User extends Model {}
|
||||
|
||||
User.prototype.default = {
|
||||
permission: 'none',
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
const serialize = user => {
|
||||
let tmp
|
||||
return {
|
||||
@ -26,6 +17,7 @@ const serialize = user => {
|
||||
}
|
||||
|
||||
const deserialize = user => ({
|
||||
permission: 'none',
|
||||
...user,
|
||||
authProviders: parseProp('user', user, 'authProviders', undefined),
|
||||
groups: parseProp('user', user, 'groups', []),
|
||||
@ -33,10 +25,6 @@ const deserialize = user => ({
|
||||
})
|
||||
|
||||
export class Users extends Collection {
|
||||
get Model() {
|
||||
return User
|
||||
}
|
||||
|
||||
async create(properties) {
|
||||
const { email } = properties
|
||||
|
||||
@ -45,11 +33,8 @@ export class Users extends Collection {
|
||||
throw new Error(`the user ${email} already exists`)
|
||||
}
|
||||
|
||||
// Create the user object.
|
||||
const user = new User(serialize(properties))
|
||||
|
||||
// Adds the user to the collection.
|
||||
return /* await */ this.add(user)
|
||||
return /* await */ this.add(serialize(properties))
|
||||
}
|
||||
|
||||
async save(user) {
|
||||
|
@ -55,7 +55,7 @@ export function extractProperty(obj, prop) {
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
export const getUserPublicProperties = user =>
|
||||
pick(user.properties || user, 'authProviders', 'id', 'email', 'groups', 'permission', 'preferences')
|
||||
pick(user, 'authProviders', 'id', 'email', 'groups', 'permission', 'preferences')
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { invalidCredentials, noSuchObject } from 'xo-common/api-errors.js'
|
||||
import { parseDuration } from '@vates/parse-duration'
|
||||
|
||||
import patch from '../patch.mjs'
|
||||
import Token, { Tokens } from '../models/token.mjs'
|
||||
import { Tokens } from '../models/token.mjs'
|
||||
import { forEach, generateToken } from '../utils.mjs'
|
||||
|
||||
// ===================================================================
|
||||
@ -183,18 +183,17 @@ export default class {
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
const token = new Token({
|
||||
const token = {
|
||||
created_at: now,
|
||||
description,
|
||||
id: await generateToken(),
|
||||
user_id: userId,
|
||||
expiration: now + duration,
|
||||
})
|
||||
}
|
||||
|
||||
await this._tokens.add(token)
|
||||
|
||||
// TODO: use plain properties directly.
|
||||
return token.properties
|
||||
return token
|
||||
}
|
||||
|
||||
async deleteAuthenticationToken(id) {
|
||||
@ -225,12 +224,11 @@ export default class {
|
||||
async getAuthenticationToken(properties) {
|
||||
const id = typeof properties === 'string' ? properties : properties.id
|
||||
|
||||
let token = await this._tokens.first(properties)
|
||||
const token = await this._tokens.first(properties)
|
||||
if (token === undefined) {
|
||||
throw noSuchAuthenticationToken(id)
|
||||
}
|
||||
|
||||
token = token.properties
|
||||
unserialize(token)
|
||||
|
||||
if (!(token.expiration > Date.now())) {
|
||||
|
@ -28,7 +28,7 @@ export default class {
|
||||
}
|
||||
|
||||
createCloudConfig(cloudConfig) {
|
||||
return this._db.add(cloudConfig).properties
|
||||
return this._db.add(cloudConfig)
|
||||
}
|
||||
|
||||
async updateCloudConfig({ id, name, template }) {
|
||||
@ -54,6 +54,6 @@ export default class {
|
||||
if (cloudConfig === undefined) {
|
||||
throw noSuchObject(id, 'cloud config')
|
||||
}
|
||||
return cloudConfig.properties
|
||||
return cloudConfig
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ const serialize = job => {
|
||||
|
||||
class JobsDb extends Collection {
|
||||
async create(job) {
|
||||
return normalize((await this.add(serialize(job))).properties)
|
||||
return normalize(await this.add(serialize(job)))
|
||||
}
|
||||
|
||||
async save(job) {
|
||||
@ -137,12 +137,11 @@ export default class Jobs {
|
||||
}
|
||||
|
||||
async getJob(id, type) {
|
||||
let job = await this._jobs.first(id)
|
||||
if (job === undefined || (type !== undefined && job.properties.type !== type)) {
|
||||
const job = await this._jobs.first(id)
|
||||
if (job === undefined || (type !== undefined && job.type !== type)) {
|
||||
throw noSuchObject(id, 'job')
|
||||
}
|
||||
|
||||
job = job.properties
|
||||
job.runId = this._runningJobs[id]
|
||||
|
||||
return job
|
||||
|
@ -49,9 +49,8 @@ export default class {
|
||||
return plugin
|
||||
}
|
||||
|
||||
async _getPluginMetadata(id) {
|
||||
const metadata = await this._pluginsMetadata.first(id)
|
||||
return metadata?.properties
|
||||
_getPluginMetadata(id) {
|
||||
return this._pluginsMetadata.first(id)
|
||||
}
|
||||
|
||||
async registerPlugin(name, instance, configurationSchema, configurationPresets, description, testSchema, version) {
|
||||
|
@ -29,7 +29,6 @@ import { generateToken } from '../utils.mjs'
|
||||
|
||||
const DEBOUNCE_TIME_PROXY_STATE = 60000
|
||||
|
||||
const extractProperties = _ => _.properties
|
||||
const synchronizedWrite = synchronized()
|
||||
|
||||
const log = createLogger('xo:proxy')
|
||||
@ -165,7 +164,7 @@ export default class Proxy {
|
||||
if (proxy === undefined) {
|
||||
throw noSuchObject(id, 'proxy')
|
||||
}
|
||||
return extractProperties(proxy)
|
||||
return proxy
|
||||
}
|
||||
|
||||
async getProxy(id) {
|
||||
@ -190,7 +189,7 @@ export default class Proxy {
|
||||
)
|
||||
|
||||
patch(proxy, { address, authenticationToken, name, vmUuid })
|
||||
return this._db.update(proxy).then(extractProperties)
|
||||
return this._db.update(proxy)
|
||||
}
|
||||
|
||||
async upgradeProxyAppliance(id, ignoreRunningJobs = false) {
|
||||
|
@ -153,7 +153,7 @@ export default class {
|
||||
if (remote === undefined) {
|
||||
throw noSuchObject(id, 'remote')
|
||||
}
|
||||
return remote.properties
|
||||
return remote
|
||||
}
|
||||
|
||||
async getRemoteWithCredentials(id) {
|
||||
@ -184,7 +184,7 @@ export default class {
|
||||
params.options = options
|
||||
}
|
||||
const remote = await this._remotes.add(params)
|
||||
return /* await */ this.updateRemote(remote.get('id'), { enabled: true })
|
||||
return /* await */ this.updateRemote(remote.id, { enabled: true })
|
||||
}
|
||||
|
||||
updateRemote(id, { enabled, name, options, proxy, url }) {
|
||||
@ -215,7 +215,7 @@ export default class {
|
||||
|
||||
patch(remote, props)
|
||||
|
||||
return (await this._remotes.update(remote)).properties
|
||||
return await this._remotes.update(remote)
|
||||
}
|
||||
|
||||
async removeRemote(id) {
|
||||
|
@ -73,16 +73,14 @@ export default class Scheduling {
|
||||
}
|
||||
|
||||
async createSchedule({ cron, enabled, jobId, name = '', timezone, userId }) {
|
||||
const schedule = (
|
||||
await this._db.add({
|
||||
cron,
|
||||
enabled,
|
||||
jobId,
|
||||
name,
|
||||
timezone,
|
||||
userId,
|
||||
})
|
||||
).properties
|
||||
const schedule = await this._db.add({
|
||||
cron,
|
||||
enabled,
|
||||
jobId,
|
||||
name,
|
||||
timezone,
|
||||
userId,
|
||||
})
|
||||
this._start(schedule)
|
||||
return schedule
|
||||
}
|
||||
@ -92,7 +90,7 @@ export default class Scheduling {
|
||||
if (schedule === undefined) {
|
||||
throw noSuchObject(id, 'schedule')
|
||||
}
|
||||
return schedule.properties
|
||||
return schedule
|
||||
}
|
||||
|
||||
async getAllSchedules() {
|
||||
|
@ -85,7 +85,7 @@ export default class {
|
||||
// TODO: use plain objects
|
||||
const user = await this._users.create(properties)
|
||||
|
||||
return user.properties
|
||||
return user
|
||||
}
|
||||
|
||||
async deleteUser(id) {
|
||||
@ -183,7 +183,7 @@ export default class {
|
||||
// TODO: this method will no longer be async when users are
|
||||
// integrated to the main collection.
|
||||
async getUser(id) {
|
||||
const user = (await this._getUser(id)).properties
|
||||
const user = await this._getUser(id)
|
||||
|
||||
// TODO: remove when no longer the email property has been
|
||||
// completely eradicated.
|
||||
@ -200,7 +200,7 @@ export default class {
|
||||
// TODO: change `email` by `username`.
|
||||
const user = await this._users.first({ email: username })
|
||||
if (user !== undefined) {
|
||||
return user.properties
|
||||
return user
|
||||
}
|
||||
|
||||
if (returnNullIfMissing) {
|
||||
@ -323,7 +323,7 @@ export default class {
|
||||
|
||||
async createGroup({ name, provider, providerGroupId }) {
|
||||
// TODO: use plain objects.
|
||||
const group = (await this._groups.create(name, provider, providerGroupId)).properties
|
||||
const group = await this._groups.create(name, provider, providerGroupId)
|
||||
|
||||
return group
|
||||
}
|
||||
@ -362,7 +362,7 @@ export default class {
|
||||
throw noSuchObject(id, 'group')
|
||||
}
|
||||
|
||||
return group.properties
|
||||
return group
|
||||
}
|
||||
|
||||
async getAllGroups() {
|
||||
|
@ -120,7 +120,7 @@ export default class {
|
||||
username,
|
||||
})
|
||||
|
||||
return server.properties
|
||||
return server
|
||||
}
|
||||
|
||||
async unregisterXenServer(id) {
|
||||
@ -148,39 +148,39 @@ export default class {
|
||||
throw new Error('this entry require disconnecting the server to update it')
|
||||
}
|
||||
|
||||
if (label !== undefined) server.set('label', label || undefined)
|
||||
if (host) server.set('host', host)
|
||||
if (username) server.set('username', username)
|
||||
if (password) server.set('password', password)
|
||||
if (label !== undefined) server.label = label || undefined
|
||||
if (host) server.host = host
|
||||
if (username) server.username = username
|
||||
if (password) server.password = password
|
||||
|
||||
if (error !== undefined) {
|
||||
server.set('error', error)
|
||||
server.error = error
|
||||
}
|
||||
|
||||
if (enabled !== undefined) {
|
||||
server.set('enabled', enabled)
|
||||
server.enabled = enabled
|
||||
}
|
||||
|
||||
if (readOnly !== undefined) {
|
||||
server.set('readOnly', readOnly)
|
||||
server.readOnly = readOnly
|
||||
if (xapi !== undefined) {
|
||||
xapi.readOnly = readOnly
|
||||
}
|
||||
}
|
||||
|
||||
if (allowUnauthorized !== undefined) {
|
||||
server.set('allowUnauthorized', allowUnauthorized)
|
||||
server.allowUnauthorized = allowUnauthorized
|
||||
}
|
||||
|
||||
if (httpProxy !== undefined) {
|
||||
// if value is null, pass undefined to the model , so it will delete this optionnal property from the Server object
|
||||
server.set('httpProxy', httpProxy === null ? undefined : httpProxy)
|
||||
server.httpProxy = httpProxy === null ? undefined : httpProxy
|
||||
}
|
||||
await this._servers.update(server)
|
||||
}
|
||||
|
||||
async getXenServer(id) {
|
||||
return (await this._getXenServer(id)).properties
|
||||
return await this._getXenServer(id)
|
||||
}
|
||||
|
||||
// TODO: this method will no longer be async when servers are
|
||||
|
Loading…
Reference in New Issue
Block a user