Add support for extended attributes
This commit is contained in:
parent
ba8e0396b8
commit
bb4a786b41
@ -22,6 +22,12 @@ class Node extends Model {
|
|||||||
descriptor_type: { type: String, default: NodeDescriptorType.File },
|
descriptor_type: { type: String, default: NodeDescriptorType.File },
|
||||||
uploaded_file_id: String,
|
uploaded_file_id: String,
|
||||||
|
|
||||||
|
extended_attributes: [{
|
||||||
|
name: String,
|
||||||
|
value: String, // base64 encoded binary buffer value
|
||||||
|
// There's position, but it's legacy for macOS, so going to exclude it for now.
|
||||||
|
}],
|
||||||
|
|
||||||
deleted: { type: Boolean, default: false },
|
deleted: { type: Boolean, default: false },
|
||||||
root: { type: Boolean, default: false },
|
root: { type: Boolean, default: false },
|
||||||
}
|
}
|
||||||
@ -56,6 +62,8 @@ class Node extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async get_path(path, workspace = 'mainline') {
|
static async get_path(path, workspace = 'mainline') {
|
||||||
|
if ( path === '/' ) return this.get_root()
|
||||||
|
|
||||||
const [pied_parent_path, pied_name] = this.path_parts(path)
|
const [pied_parent_path, pied_name] = this.path_parts(path)
|
||||||
|
|
||||||
const nodes = await this.find({
|
const nodes = await this.find({
|
||||||
@ -142,6 +150,28 @@ class Node extends Model {
|
|||||||
return [...nodes, ...mainline_nodes].filter(x => !x.deleted)
|
return [...nodes, ...mainline_nodes].filter(x => !x.deleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_xattr(name, value) {
|
||||||
|
this.guarantee_xattrs()
|
||||||
|
this.remove_xattr(name)
|
||||||
|
this.extended_attributes.push({ name, value })
|
||||||
|
}
|
||||||
|
|
||||||
|
get_xattr(name) {
|
||||||
|
this.guarantee_xattrs()
|
||||||
|
return this.extended_attributes.find(attr => attr.name === name)
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_xattr(name) {
|
||||||
|
this.guarantee_xattrs()
|
||||||
|
this.extended_attributes = this.extended_attributes.filter(attr => attr.name !== name)
|
||||||
|
}
|
||||||
|
|
||||||
|
guarantee_xattrs() {
|
||||||
|
if ( !Array.isArray(this.extended_attributes) ) {
|
||||||
|
this.extended_attributes = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
to_api() {
|
to_api() {
|
||||||
return {
|
return {
|
||||||
pied_name: this.pied_name,
|
pied_name: this.pied_name,
|
||||||
|
17
app/ws/routes/fs.xattr.get.js
Normal file
17
app/ws/routes/fs.xattr.get.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
const { Errors } = require('../../shared')
|
||||||
|
|
||||||
|
module.exports = exports = async (message, di) => {
|
||||||
|
const Node = di.models.get('fs:Node')
|
||||||
|
const { path, name } = message.data()
|
||||||
|
|
||||||
|
const node = await Node.get_path(path, message.socket.session.overlay_name || 'mainline')
|
||||||
|
if ( !node ) {
|
||||||
|
return message.send_response(
|
||||||
|
message.fresh().error(Errors.NodeDoesNotExist)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
message.send_response(
|
||||||
|
message.fresh().data({ node: node.to_api(), value: node.get_xattr(name)?.value })
|
||||||
|
)
|
||||||
|
}
|
19
app/ws/routes/fs.xattr.list.js
Normal file
19
app/ws/routes/fs.xattr.list.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const { Errors } = require('../../shared')
|
||||||
|
|
||||||
|
module.exports = exports = async (message, di) => {
|
||||||
|
const Node = di.models.get('fs:Node')
|
||||||
|
const { path } = message.data()
|
||||||
|
|
||||||
|
const node = await Node.get_path(path, message.socket.session.overlay_name || 'mainline')
|
||||||
|
if ( !node ) {
|
||||||
|
return message.send_response(
|
||||||
|
message.fresh().error(Errors.NodeDoesNotExist)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.guarantee_xattrs()
|
||||||
|
|
||||||
|
message.send_response(
|
||||||
|
message.fresh().data({ node: node.to_api(), names: node.extended_attributes.map(x => x.name) })
|
||||||
|
)
|
||||||
|
}
|
20
app/ws/routes/fs.xattr.remove.js
Normal file
20
app/ws/routes/fs.xattr.remove.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const { Errors } = require('../../shared')
|
||||||
|
|
||||||
|
module.exports = exports = async (message, di) => {
|
||||||
|
const Node = di.models.get('fs:Node')
|
||||||
|
const { path, name } = message.data()
|
||||||
|
|
||||||
|
const node = await Node.get_path(path, message.socket.session.overlay_name || 'mainline')
|
||||||
|
if ( !node ) {
|
||||||
|
return message.send_response(
|
||||||
|
message.fresh().error(Errors.NodeDoesNotExist)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.remove_xattr(name)
|
||||||
|
await node.save()
|
||||||
|
|
||||||
|
message.send_response(
|
||||||
|
message.fresh().data({ node: node.to_api() })
|
||||||
|
)
|
||||||
|
}
|
20
app/ws/routes/fs.xattr.set.js
Normal file
20
app/ws/routes/fs.xattr.set.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const { Errors } = require('../../shared')
|
||||||
|
|
||||||
|
module.exports = exports = async (message, di) => {
|
||||||
|
const Node = di.models.get('fs:Node')
|
||||||
|
const { path, name, value } = message.data()
|
||||||
|
|
||||||
|
const node = await Node.get_path(path, message.socket.session.overlay_name || 'mainline')
|
||||||
|
if ( !node ) {
|
||||||
|
return message.send_response(
|
||||||
|
message.fresh().error(Errors.NodeDoesNotExist)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
node.set_xattr(name, value)
|
||||||
|
await node.save()
|
||||||
|
|
||||||
|
message.send_response(
|
||||||
|
message.fresh().data({ node: node.to_api() })
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user