Browse Source

feat(nextcloud): Implement WebDAV proppatch remove

pull/520/head
jld3103 1 year ago
parent
commit
1fb9224c9d
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 14
      packages/nextcloud/lib/src/webdav/client.dart
  2. 23
      packages/nextcloud/lib/src/webdav/webdav.dart
  3. 101
      packages/nextcloud/lib/src/webdav/webdav.g.dart
  4. 52
      packages/nextcloud/test/webdav_test.dart

14
packages/nextcloud/lib/src/webdav/client.dart

@ -266,12 +266,15 @@ class WebDavClient {
/// Updates the props of the resource at [path]. /// Updates the props of the resource at [path].
/// ///
/// The props in [set] will be updated.
/// The props in [remove] will be removed.
/// Returns true if the update was successful. /// Returns true if the update was successful.
/// See http://www.webdav.org/specs/rfc2518.html#METHOD_PROPPATCH for more information. /// See http://www.webdav.org/specs/rfc2518.html#METHOD_PROPPATCH for more information.
Future<bool> proppatch( Future<bool> proppatch(
final String path, final String path, {
final WebDavProp prop, final WebDavProp? set,
) async { final WebDavPropWithoutValues? remove,
}) async {
final response = await _send( final response = await _send(
'PROPPATCH', 'PROPPATCH',
_constructPath(path), _constructPath(path),
@ -279,7 +282,10 @@ class WebDavClient {
data: Stream.value( data: Stream.value(
Uint8List.fromList( Uint8List.fromList(
utf8.encode( utf8.encode(
WebDavPropertyupdate(set: WebDavSet(prop: prop)).toXmlElement(namespaces: namespaces).toXmlString(), WebDavPropertyupdate(
set: set != null ? WebDavSet(prop: set) : null,
remove: remove != null ? WebDavRemove(prop: remove) : null,
).toXmlElement(namespaces: namespaces).toXmlString(),
), ),
), ),
), ),

23
packages/nextcloud/lib/src/webdav/webdav.dart

@ -76,11 +76,15 @@ class WebDavPropstat with _$WebDavPropstatXmlSerializableMixin {
@annotation.XmlRootElement(name: 'propertyupdate', namespace: namespaceDav) @annotation.XmlRootElement(name: 'propertyupdate', namespace: namespaceDav)
class WebDavPropertyupdate with _$WebDavPropertyupdateXmlSerializableMixin { class WebDavPropertyupdate with _$WebDavPropertyupdateXmlSerializableMixin {
WebDavPropertyupdate({ WebDavPropertyupdate({
required this.set, this.set,
this.remove,
}); });
@annotation.XmlElement(name: 'set', namespace: namespaceDav) @annotation.XmlElement(name: 'set', namespace: namespaceDav, includeIfNull: false)
final WebDavSet set; final WebDavSet? set;
@annotation.XmlElement(name: 'remove', namespace: namespaceDav, includeIfNull: false)
final WebDavRemove? remove;
} }
@annotation.XmlSerializable(createMixin: true) @annotation.XmlSerializable(createMixin: true)
@ -96,6 +100,19 @@ class WebDavSet with _$WebDavSetXmlSerializableMixin {
final WebDavProp prop; // coverage:ignore-line final WebDavProp prop; // coverage:ignore-line
} }
@annotation.XmlSerializable(createMixin: true)
@annotation.XmlRootElement(name: 'remove', namespace: namespaceDav)
class WebDavRemove with _$WebDavRemoveXmlSerializableMixin {
WebDavRemove({
required this.prop,
});
factory WebDavRemove.fromXmlElement(final XmlElement element) => _$WebDavRemoveFromXmlElement(element);
@annotation.XmlElement(name: 'prop', namespace: namespaceDav)
final WebDavPropWithoutValues prop; // coverage:ignore-line
}
@annotation.XmlSerializable(createMixin: true) @annotation.XmlSerializable(createMixin: true)
@annotation.XmlRootElement(name: 'propfind', namespace: namespaceDav) @annotation.XmlRootElement(name: 'propfind', namespace: namespaceDav)
class WebDavPropfind with _$WebDavPropfindXmlSerializableMixin { class WebDavPropfind with _$WebDavPropfindXmlSerializableMixin {

101
packages/nextcloud/lib/src/webdav/webdav.g.dart

@ -221,9 +221,18 @@ void _$WebDavPropertyupdateBuildXmlChildren(WebDavPropertyupdate instance, XmlBu
{Map<String, String> namespaces = const {}}) { {Map<String, String> namespaces = const {}}) {
final set = instance.set; final set = instance.set;
final setSerialized = set; final setSerialized = set;
builder.element('set', namespace: 'DAV:', nest: () { if (setSerialized != null) {
setSerialized.buildXmlChildren(builder, namespaces: namespaces); builder.element('set', namespace: 'DAV:', nest: () {
}); setSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
final remove = instance.remove;
final removeSerialized = remove;
if (removeSerialized != null) {
builder.element('remove', namespace: 'DAV:', nest: () {
removeSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
} }
void _$WebDavPropertyupdateBuildXmlElement(WebDavPropertyupdate instance, XmlBuilder builder, void _$WebDavPropertyupdateBuildXmlElement(WebDavPropertyupdate instance, XmlBuilder builder,
@ -234,8 +243,11 @@ void _$WebDavPropertyupdateBuildXmlElement(WebDavPropertyupdate instance, XmlBui
} }
WebDavPropertyupdate _$WebDavPropertyupdateFromXmlElement(XmlElement element) { WebDavPropertyupdate _$WebDavPropertyupdateFromXmlElement(XmlElement element) {
final set = element.getElement('set', namespace: 'DAV:')!; final set = element.getElement('set', namespace: 'DAV:');
return WebDavPropertyupdate(set: WebDavSet.fromXmlElement(set)); final remove = element.getElement('remove', namespace: 'DAV:');
return WebDavPropertyupdate(
set: set != null ? WebDavSet.fromXmlElement(set) : null,
remove: remove != null ? WebDavRemove.fromXmlElement(remove) : null);
} }
List<XmlAttribute> _$WebDavPropertyupdateToXmlAttributes(WebDavPropertyupdate instance, List<XmlAttribute> _$WebDavPropertyupdateToXmlAttributes(WebDavPropertyupdate instance,
@ -249,9 +261,22 @@ List<XmlNode> _$WebDavPropertyupdateToXmlChildren(WebDavPropertyupdate instance,
final children = <XmlNode>[]; final children = <XmlNode>[];
final set = instance.set; final set = instance.set;
final setSerialized = set; final setSerialized = set;
final setConstructed = XmlElement(XmlName('set', namespaces['DAV:']), final setConstructed = setSerialized != null
setSerialized.toXmlAttributes(namespaces: namespaces), setSerialized.toXmlChildren(namespaces: namespaces)); ? XmlElement(XmlName('set', namespaces['DAV:']), setSerialized.toXmlAttributes(namespaces: namespaces),
children.add(setConstructed); setSerialized.toXmlChildren(namespaces: namespaces))
: null;
if (setConstructed != null) {
children.add(setConstructed);
}
final remove = instance.remove;
final removeSerialized = remove;
final removeConstructed = removeSerialized != null
? XmlElement(XmlName('remove', namespaces['DAV:']), removeSerialized.toXmlAttributes(namespaces: namespaces),
removeSerialized.toXmlChildren(namespaces: namespaces))
: null;
if (removeConstructed != null) {
children.add(removeConstructed);
}
return children; return children;
} }
@ -338,6 +363,66 @@ mixin _$WebDavSetXmlSerializableMixin {
_$WebDavSetToXmlElement(this as WebDavSet, namespaces: namespaces); _$WebDavSetToXmlElement(this as WebDavSet, namespaces: namespaces);
} }
void _$WebDavRemoveBuildXmlChildren(WebDavRemove instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) {
final prop = instance.prop;
final propSerialized = prop;
builder.element('prop', namespace: 'DAV:', nest: () {
propSerialized.buildXmlChildren(builder, namespaces: namespaces);
});
}
void _$WebDavRemoveBuildXmlElement(WebDavRemove instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) {
builder.element('remove', namespace: 'DAV:', namespaces: namespaces, nest: () {
instance.buildXmlChildren(builder, namespaces: namespaces);
});
}
WebDavRemove _$WebDavRemoveFromXmlElement(XmlElement element) {
final prop = element.getElement('prop', namespace: 'DAV:')!;
return WebDavRemove(prop: WebDavPropWithoutValues.fromXmlElement(prop));
}
List<XmlAttribute> _$WebDavRemoveToXmlAttributes(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
final attributes = <XmlAttribute>[];
return attributes;
}
List<XmlNode> _$WebDavRemoveToXmlChildren(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
final children = <XmlNode>[];
final prop = instance.prop;
final propSerialized = prop;
final propConstructed = XmlElement(XmlName('prop', namespaces['DAV:']),
propSerialized.toXmlAttributes(namespaces: namespaces), propSerialized.toXmlChildren(namespaces: namespaces));
children.add(propConstructed);
return children;
}
XmlElement _$WebDavRemoveToXmlElement(WebDavRemove instance, {Map<String, String?> namespaces = const {}}) {
return XmlElement(
XmlName('remove', namespaces['DAV:']),
[...namespaces.toXmlAttributes(), ...instance.toXmlAttributes(namespaces: namespaces)],
instance.toXmlChildren(namespaces: namespaces));
}
mixin _$WebDavRemoveXmlSerializableMixin {
void buildXmlChildren(XmlBuilder builder, {Map<String, String> namespaces = const {}}) =>
_$WebDavRemoveBuildXmlChildren(this as WebDavRemove, builder, namespaces: namespaces);
void buildXmlElement(XmlBuilder builder, {Map<String, String> namespaces = const {}}) =>
_$WebDavRemoveBuildXmlElement(this as WebDavRemove, builder, namespaces: namespaces);
List<XmlAttribute> toXmlAttributes({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlAttributes(this as WebDavRemove, namespaces: namespaces);
List<XmlNode> toXmlChildren({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlChildren(this as WebDavRemove, namespaces: namespaces);
XmlElement toXmlElement({Map<String, String?> namespaces = const {}}) =>
_$WebDavRemoveToXmlElement(this as WebDavRemove, namespaces: namespaces);
}
void _$WebDavPropfindBuildXmlChildren(WebDavPropfind instance, XmlBuilder builder, void _$WebDavPropfindBuildXmlChildren(WebDavPropfind instance, XmlBuilder builder,
{Map<String, String> namespaces = const {}}) { {Map<String, String> namespaces = const {}}) {
final prop = instance.prop; final prop = instance.prop;

52
packages/nextcloud/test/webdav_test.dart

@ -324,7 +324,7 @@ void main() {
final id = response.headers['oc-fileid']!.first; final id = response.headers['oc-fileid']!.first;
await client.webdav.proppatch( await client.webdav.proppatch(
'test.txt', 'test.txt',
WebDavProp( set: WebDavProp(
ocfavorite: 1, ocfavorite: 1,
), ),
); );
@ -356,7 +356,7 @@ void main() {
final updated = await client.webdav.proppatch( final updated = await client.webdav.proppatch(
'test.txt', 'test.txt',
WebDavProp( set: WebDavProp(
ocfavorite: 1, ocfavorite: 1,
nccreationtime: createdEpoch, nccreationtime: createdEpoch,
), ),
@ -380,5 +380,53 @@ void main() {
expect(DateTime.fromMillisecondsSinceEpoch(props.nccreationtime! * 1000).isAtSameMomentAs(createdDate), isTrue); expect(DateTime.fromMillisecondsSinceEpoch(props.nccreationtime! * 1000).isAtSameMomentAs(createdDate), isTrue);
expectDateInReasonableTimeRange(DateTime.fromMillisecondsSinceEpoch(props.ncuploadtime! * 1000), uploadTime); expectDateInReasonableTimeRange(DateTime.fromMillisecondsSinceEpoch(props.ncuploadtime! * 1000), uploadTime);
}); });
test('Remove properties', () async {
await client.webdav.put(Uint8List.fromList(utf8.encode('test')), 'test.txt');
var updated = await client.webdav.proppatch(
'test.txt',
set: WebDavProp(
ocfavorite: 1,
),
);
expect(updated, isTrue);
var props = (await client.webdav.propfind(
'test.txt',
prop: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
nccreationtime: true,
ncuploadtime: true,
),
))
.responses
.single
.propstats
.first
.prop;
expect(props.ocfavorite, 1);
updated = await client.webdav.proppatch(
'test.txt',
remove: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
),
);
expect(updated, isFalse);
props = (await client.webdav.propfind(
'test.txt',
prop: WebDavPropWithoutValues.fromBools(
ocfavorite: true,
),
))
.responses
.single
.propstats
.first
.prop;
expect(props.ocfavorite, 0);
});
}); });
} }

Loading…
Cancel
Save