Skip to content

Commit 725d264

Browse files
committed
Fixed DB upgrade, working prototype for upload page
1 parent 421e254 commit 725d264

File tree

3 files changed

+109
-69
lines changed

3 files changed

+109
-69
lines changed

internal/configuration/database/provider/redis/Redis.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type DatabaseProvider struct {
2121
}
2222

2323
// DatabaseSchemeVersion contains the version number to be expected from the current database. If lower, an upgrade will be performed
24-
const DatabaseSchemeVersion = 6
24+
const DatabaseSchemeVersion = 7
2525

2626
// New returns an instance
2727
func New(dbConfig models.DbConnection) (DatabaseProvider, error) {
@@ -136,6 +136,20 @@ func (p DatabaseProvider) Upgrade(currentDbVersion int) {
136136
}
137137
}
138138
}
139+
// pre file request
140+
if currentDbVersion < 7 {
141+
for _, user := range p.GetAllUsers() {
142+
if user.UserLevel != models.UserLevelUser {
143+
user.GrantPermission(models.UserPermGuestUploads)
144+
}
145+
p.SaveUser(user, false)
146+
}
147+
for _, apiKey := range p.GetAllApiKeys() {
148+
if apiKey.IsSystemKey {
149+
p.DeleteApiKey(apiKey.Id)
150+
}
151+
}
152+
}
139153
}
140154

141155
const keyDbVersion = "dbversion"

internal/configuration/database/provider/sqlite/Sqlite.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ func (p DatabaseProvider) Upgrade(currentDbVersion int) {
8282
p.DeleteApiKey(apiKey.Id)
8383
}
8484
}
85+
for _, user := range p.GetAllUsers() {
86+
if user.UserLevel != models.UserLevelUser {
87+
user.GrantPermission(models.UserPermGuestUploads)
88+
}
89+
p.SaveUser(user, false)
90+
}
8591
}
8692
}
8793

internal/webserver/web/templates/html_public_upload.tmpl

Lines changed: 88 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@
8787
<div id="fileList" class="file-list"></div>
8888

8989
<div class="text-center mt-4">
90-
<button class="btn btn-secondary" disabled>
91-
Upload (TODO)
90+
<button class="btn btn-secondary" onClick="initUpload();" id="uploadbutton">
91+
Upload
9292
</button>
9393
</div>
9494

@@ -101,39 +101,62 @@
101101

102102
<script>
103103
const fileInput = document.getElementById('fileInput');
104-
const fileList = document.getElementById('fileList');
105-
106-
fileInput.addEventListener('change', () => {
107-
fileList.innerHTML = '';
108-
109-
Array.from(fileInput.files).forEach(file => {
110-
const item = document.createElement('div');
111-
item.className = 'file-item';
112-
113-
const name = document.createElement('span');
114-
name.textContent = file.name;
115-
116-
const size = document.createElement('span');
117-
size.className = 'file-size';
118-
size.textContent = formatSize(file.size);
119-
120-
const removeBtn = document.createElement('button');
121-
removeBtn.type = 'button';
122-
removeBtn.title = "Remove";
123-
removeBtn.className = 'btn btn-sm btn-link text-light p-0 remove-entry-btn';
124-
removeBtn.innerHTML = '<i class="bi bi-x-circle"></i>';
125-
126-
removeBtn.addEventListener('click', () => {
127-
item.remove();
128-
});
104+
const fileList = document.getElementById('fileList');
105+
106+
const filesMap = new Map();
107+
108+
fileInput.addEventListener('change', () => {
109+
Array.from(fileInput.files).forEach(file => {
110+
const uuid = getUuid();
111+
112+
const item = document.createElement('div');
113+
item.className = 'file-item';
114+
item.dataset.uuid = uuid;
115+
116+
const name = document.createElement('span');
117+
name.textContent = file.name;
118+
119+
const progressText = document.createElement('span');
120+
progressText.className = 'file-size';
121+
progressText.textContent = '0%';
122+
123+
const progressBar = document.createElement('progress');
124+
progressBar.max = file.size;
125+
progressBar.value = 0;
126+
progressBar.style.width = '120px';
127+
progressBar.style.marginRight = '10px';
128+
129+
const size = document.createElement('span');
130+
size.className = 'file-size';
131+
size.textContent = formatSize(file.size);
132+
133+
const removeBtn = document.createElement('button');
134+
removeBtn.type = 'button';
135+
removeBtn.title = 'Remove';
136+
removeBtn.className = 'btn btn-sm btn-link text-light p-0';
137+
removeBtn.innerHTML = '<i class="bi bi-x-circle"></i>';
138+
139+
removeBtn.addEventListener('click', () => {
140+
filesMap.get(uuid).removed = true;
141+
item.remove();
142+
});
129143

130-
item.appendChild(name);
131-
item.appendChild(size);
132-
item.appendChild(removeBtn);
133-
fileList.appendChild(item);
144+
item.append(name, progressBar, progressText, size, removeBtn);
145+
fileList.appendChild(item);
146+
147+
filesMap.set(uuid, {
148+
uuid,
149+
file,
150+
removed: false,
151+
elements: { progressBar, progressText, removeBtn, item }
134152
});
135153
});
136154

155+
// Allow re-selecting same files
156+
fileInput.value = '';
157+
});
158+
159+
137160
function formatSize(bytes) {
138161
const units = ['B', 'KB', 'MB', 'GB'];
139162
let i = 0;
@@ -154,26 +177,24 @@ const COMPLETE_URL = "./api/chunk/uploadRequestComplete";
154177
const FILE_REQUEST_ID = "{{ .FileRequest.Id }}";
155178
const API_KEY = "{{ .FileRequest.ApiKey }}";
156179

180+
function initUpload() {
181+
const btn = document.getElementById("uploadbutton");
182+
btn.disabled = true;
183+
184+
startUpload()
185+
.catch(err => console.error(err))
186+
.finally(() => btn.disabled = false);
187+
}
157188

158189
async function startUpload() {
159-
const files = document.getElementById("fileInput").files;
160-
const status = document.getElementById("status");
161-
status.innerHTML = "";
162-
163-
for (const file of files) {
164-
const fileDiv = document.createElement("div");
165-
fileDiv.className = "file";
166-
fileDiv.innerHTML = `
167-
<strong>${file.name}</strong><br>
168-
<progress value="0" max="${file.size}"></progress>
169-
<span class="progressText">0%</span>
170-
`;
171-
status.appendChild(fileDiv);
172-
173-
const progressBar = fileDiv.querySelector("progress");
174-
const progressText = fileDiv.querySelector(".progressText");
190+
for (const entry of filesMap.values()) {
191+
if (entry.removed) continue;
192+
193+
const { file, uuid, elements } = entry;
194+
195+
// Disable delete during upload
196+
elements.removeBtn.remove();
175197

176-
const uuid = getUuid();
177198
let offset = 0;
178199

179200
while (offset < file.size) {
@@ -189,53 +210,52 @@ async function startUpload() {
189210
method: "POST",
190211
body: formData,
191212
headers: {
192-
'apikey': API_KEY,
193-
"fileRequestId": FILE_REQUEST_ID
213+
apikey: API_KEY,
214+
fileRequestId: FILE_REQUEST_ID
194215
}
195216
});
196217

197218
if (!response.ok) {
219+
elements.progressText.textContent = "Error";
198220
throw new Error(`Chunk upload failed: ${response.status}`);
199221
}
200222

201223
offset += chunk.size;
202-
progressBar.value = offset;
203-
progressText.textContent = Math.floor((offset / file.size) * 100) + "%";
224+
elements.progressBar.value = offset;
225+
elements.progressText.textContent =
226+
Math.floor((offset / file.size) * 100) + "%";
204227
}
205228

206-
// Finalize upload
207229
await finalizeUpload(file, uuid);
208-
progressText.textContent = "✔ Completed";
230+
231+
elements.progressText.textContent = "Completed";
232+
elements.item.style.opacity = "0.6";
233+
filesMap.get(uuid).removed = true;
209234
}
210235
}
211236

212237
async function finalizeUpload(file, uuid) {
213-
const headers = {
214-
"uuid": uuid,
215-
"fileRequestId": FILE_REQUEST_ID,
216-
"filename": encodeFilename(file.name),
217-
"filesize": file.size,
218-
'apikey': API_KEY,
219-
"contenttype": file.type || "application/octet-stream"
220-
};
221-
222238
const response = await fetch(COMPLETE_URL, {
223239
method: "POST",
224-
headers: headers
240+
headers: {
241+
uuid: uuid,
242+
fileRequestId: FILE_REQUEST_ID,
243+
filename: encodeFilename(file.name),
244+
filesize: file.size,
245+
contenttype: file.type || "application/octet-stream",
246+
apikey: API_KEY
247+
}
225248
});
226249

227250
if (!response.ok) {
228251
throw new Error(`Finalize failed: ${response.status}`);
229252
}
230-
231-
return response;
232253
}
233254

234255
function encodeFilename(name) {
235-
return "base64:" + btoa(unescape(encodeURIComponent(name)));
256+
return "base64:" + Base64.encode(name);
236257
}
237258
</script>
238-
<script src="./js/min/uuid.min.js"></script>
239259

240260
{{ template "pagename" "PublicUpload"}}
241261
{{ template "customjs" .}}

0 commit comments

Comments
 (0)