Repository: learningequality/kolibri

Issue:
Cannot export channels to a flash drive
## Observed behavior
I can't export channels to a flash drive as I'm constantly getting the following message: Could not find a writable drive connected to the server

## Expected behavior
It should be possible to export my channels.

## Steps to reproduce the issue
1. Install the following 0.15 alfa 2 build: https://buildkite.com/organizations/learningequality/pipelines/kolibri-windows/builds/1522/jobs/4d506e7c-949f-49ab-9824-32320614996a/artifacts/57eee854-a0f7-4743-baed-0b464a56c21c
2. Go to Device>Channels>Options and select the Export channels option
3. Select a channel and click Export

## Additional information

![2021-08-02_15-26-57](https://user-images.githubusercontent.com/79847249/127862825-76502967-c5e2-4556-afd9-693cbe05dfe6.png)

## Errors and logs
[logs.zip](https://github.com/learningequality/kolibri/files/6916892/logs.zip)

## Usage Details
 - OS: Windows 10
 - Browser: Chrome


Discussion:
https://learningequality.testquality.com defect [D4](https://learningequality.testquality.com/project/12317/result/2456386/defect/8033).
I can replicate this on both Windows 10 and on my Ubuntu dev VM on branch 0.15.x.

It gives 500 error on `/api/tasks/tasks/localdrive/` with `AttributeError: 'dict' object has no attribute 'id'`

Windows 10 | Ubuntu dev VM
--- | ---
![Win10 (start)  Running  - Oracle VM VirtualBox_019](https://user-images.githubusercontent.com/1457929/128454940-c7b4bf16-9523-4491-a0a8-311ac5894ef7.png) | ![LEDev2104 (start)  Running  - Oracle VM VirtualBox_014](https://user-images.githubusercontent.com/1457929/128455060-5ac4e81f-d9ed-4b6f-833c-9a3a9250bb56.png)

cc @rtibbles (and @jredrejo since we discussed it on Slack)

Could you attach log files for this so we can see the full traceback? 
This is from my dev VM, let me know if you need the logs from the Win 10 one too.

[debug.txt](https://github.com/learningequality/kolibri/files/6943939/debug.txt) (full debug.txt was huge, I copied only the relevant day)
[kolibri.txt](https://github.com/learningequality/kolibri/files/6943940/kolibri.txt)

@radinamatic and @rtibbles the channel export functionality is now working correctly in this [build](https://buildkite.com/learningequality/kolibri-windows/builds/1751) - - drives are displayed correctly and I am able to select one and export channels.
A bug that fixed itself...? 😛 
There was another issue opened at one point that seemed to be non-reproducible where an external drive suddenly became unfindable during export, I wonder if this is another manifestation of that?
I guess I was too happy to see it working but now I have to report that both channel export and import to a flash drive are not working and I'm getting the 500 errors in the console while I can still see that the flash drive is correctly attached to the device and is accessible. Tried restarting Kolibri and tried with different channels. Here are the logs:
[logs.zip](https://github.com/learningequality/kolibri/files/7060691/logs.zip)


Resolving patch:
diff --git a/kolibri/core/content/management/commands/scanforcontent.py b/kolibri/core/content/management/commands/scanforcontent.py
--- a/kolibri/core/content/management/commands/scanforcontent.py
+++ b/kolibri/core/content/management/commands/scanforcontent.py
@@ -113,7 +113,7 @@ def database_file_is_newer(self, channel_id, disk_path):
             disk_channel = read_channel_metadata_from_db_file(disk_path)
             db_channel = ChannelMetadata.objects.get(id=channel_id)
             # the version in the primary database is older than the one on disk
-            return disk_channel.version > db_channel.version
+            return disk_channel["version"] > db_channel.version
         except DatabaseError:
             # problem with the database on disk; it can't be considered newer
             return False
diff --git a/kolibri/core/content/utils/channels.py b/kolibri/core/content/utils/channels.py
--- a/kolibri/core/content/utils/channels.py
+++ b/kolibri/core/content/utils/channels.py
@@ -121,17 +121,17 @@ def get_channels_for_data_folder(datafolder):
             continue
         channel_data = {
             "path": path,
-            "id": channel.id,
-            "name": channel.name,
-            "description": channel.description,
-            "tagline": getattr(channel, "tagline", ""),
-            "thumbnail": channel.thumbnail,
-            "version": channel.version,
-            "root": channel.root_id,
-            "author": channel.author,
-            "last_updated": getattr(channel, "last_updated", None),
-            "lang_code": getattr(channel, "lang_code", None),
-            "lang_name": getattr(channel, "lang_name", None),
+            "id": channel["id"],
+            "name": channel["name"],
+            "description": channel["description"],
+            "tagline": channel.get("tagline", ""),
+            "thumbnail": channel["thumbnail"],
+            "version": channel["version"],
+            "root": channel["root_id"],
+            "author": channel["author"],
+            "last_updated": channel.get("last_updated"),
+            "lang_code": channel.get("lang_code"),
+            "lang_name": channel.get("lang_name"),
         }
         channels.append(channel_data)
     return channels
diff --git a/kolibri/core/tasks/api.py b/kolibri/core/tasks/api.py
--- a/kolibri/core/tasks/api.py
+++ b/kolibri/core/tasks/api.py
@@ -927,7 +927,7 @@ def channeldiffstats(self, request):
             channel_metadata = read_channel_metadata_from_db_file(
                 get_content_database_file_path(channel_id, drive.datafolder)
             )
-            job_metadata["new_channel_version"] = channel_metadata.version
+            job_metadata["new_channel_version"] = channel_metadata["version"]
         else:
             raise serializers.ValidationError(
                 "'method' field should either be 'network' or 'disk'."


Test patch: