diff --git a/Tesses.CrossLang.PackageServer/src/backend/package.tcross b/Tesses.CrossLang.PackageServer/src/backend/package.tcross index 2d81ece..5808e98 100644 --- a/Tesses.CrossLang.PackageServer/src/backend/package.tcross +++ b/Tesses.CrossLang.PackageServer/src/backend/package.tcross @@ -1,3 +1,160 @@ +func DB.DeletePackages(email,password, packageListString) +{ + if(TypeOf(email) != "String" || TypeOf(password) != "String") + { + return "Email or password not set in form"; + } + if(TypeOf(packageListString) != "String") + { + return "Package List not set in form"; + } + + var accountId = DB.GetAccountId(email, password); + + var failed = ""; + + func removeVersion(name, version) + { + var v = Version.Parse(version); + if(name.Length == 0) + { + failed += "No package name\n"; + return; + } + if(v == null) + { + failed += "No package version\n"; + return; + } + + DB.Lock(); + var db = DB.Open(); + var exec = Sqlite.Exec(db, $"SELECT * FROM packages WHERE packageName = {Sqlite.Escape(name)};"); + Sqlite.Close(db); + DB.Unlock(); + + if(exec.Length == 1) + { + var id = ParseLong(exec[0].id); + if(ParseLong(exec[0].accountId) != accountId) + { + failed += $"User does not own package {name}\n"; + return; + } + DB.Lock(); + db = DB.Open(); + exec = Sqlite.Exec(db, $"SELECT * FROM versions WHERE packageId = {id};"); + var versionId = -1; + var shallEraseEntirePackage = false; + if(TypeOf(exec) == "List") + { + if(exec.Length == 1 && ParseLong(exec[0].version) == v.VersionInt) + { + shallEraseEntirePackage=true; + } + else { + each(var item : exec) + { + if(ParseLong(item.version) == v.VersionInt) + { + versionId = ParseLong(item.id); + break; + } + } + } + } + + if(versionId > -1) + { + Sqlite.Exec(db, $"DELETE FROM versions WHERE id = {versionId};"); + FS.Local.DeleteFile(DB.working / "Packages" / name / $"{name}-{version}.crvm"); + } + Sqlite.Close(db); + DB.Unlock(); + if(shallEraseEntirePackage) { + removePackage(name); + } + if(!shallEraseEntirePackage && versionId == -1) + { + failed += $"Failed to remove package {name}-{version}.crvm\n"; + } + } + else { + failed += $"Could not find package {name}-{version}.crvm\n"; + } + } + + func removePackage(name) + { + if(name.Length == 0) + { + failed += "No package name\n"; + return; + } + DB.Lock(); + var db = DB.Open(); + var exec = Sqlite.Exec(db, $"SELECT * FROM packages WHERE packageName = {Sqlite.Escape(name)};"); + Sqlite.Close(db); + DB.Unlock(); + + if(exec.Length == 1) + { + var id = ParseLong(exec[0].id); + if(ParseLong(exec[0].accountId) != accountId) + { + failed += $"User does not own package {name}\n"; + return; + } + DB.Lock(); + db = DB.Open(); + exec = Sqlite.Exec(db, $"DELETE FROM versions WHERE packageId = {id};"); + exec = Sqlite.Exec(db, $"DELETE FROM packages WHERE id = {id};"); + Sqlite.Close(db); + DB.Unlock(); + if(FS.Local.DirectoryExists(DB.working / "Packages" / name)) + FS.Local.DeleteDirectoryRecurse(DB.working / "Packages" / name); + } + else { + failed += $"Could not find package {name}"; + } + } + + + each(var item : packageListString.Replace("\r","").Split("\n")) + { + var stageOrAstrisk = item.LastIndexOf('-'); + if(stageOrAstrisk > -1) + { + if(item[stageOrAstrisk+1] == '*') + { + removePackage(item.Substring(0, stageOrAstrisk)); + } + else if(item[stageOrAstrisk+1] == 'd' || item[stageOrAstrisk+1] == 'a' || item[stageOrAstrisk+1] == 'b' || item[stageOrAstrisk+1] == 'p') { + var versionIdx = item.LastIndexOf('-',stageOrAstrisk-1); + if(versionIdx > -1) + { + removeVersion(item.Substring(0,versionIdx),item.Substring(versionIdx+1)); + + + } else { + failed += $"{item}, Failed to find version part\n"; + } + + } + else { + failed += $"{item}, Invalid version\n"; + continue; + } + } + else { + failed += $"{item}, No version at all\n"; + } + } + + if(failed.Length > 0) return failed; + + return "Success"; +} func DB.CanUploadPackagePrefix(userId, packageName) { var prefix = packageName.Split(".",true,2); diff --git a/Tesses.CrossLang.PackageServer/src/pages/account.tcross b/Tesses.CrossLang.PackageServer/src/pages/account.tcross index a96484e..a086ef6 100644 --- a/Tesses.CrossLang.PackageServer/src/pages/account.tcross +++ b/Tesses.CrossLang.PackageServer/src/pages/account.tcross @@ -85,6 +85,7 @@ func Pages.Account(ctx) +
@@ -99,9 +100,12 @@ func Pages.Account(ctx) Admin + Delete Packages Logout + +

diff --git a/Tesses.CrossLang.PackageServer/src/pages/delete-packages.tcross b/Tesses.CrossLang.PackageServer/src/pages/delete-packages.tcross new file mode 100644 index 0000000..5b9ba45 --- /dev/null +++ b/Tesses.CrossLang.PackageServer/src/pages/delete-packages.tcross @@ -0,0 +1,33 @@ +func Pages.DeletePackages(ctx) +{ + var pages = [ + { + active = false, + route = "/packages", + text = "Packages" + }, + { + active = false, + route = "/upload", + text = "Upload" + }, + DB.LoginButton(ctx,false) + ]; + var form =
+ Please don{"'"}t do this unless you absolutely need to as it may break other software + + +

Your credentials are needed due to this being a dangerous action

+
+ + +
+
+ + +
+ + +
; + return Shell("Delete packages", pages, form); +} \ No newline at end of file diff --git a/Tesses.CrossLang.PackageServer/src/program.tcross b/Tesses.CrossLang.PackageServer/src/program.tcross index 22d6151..55d94f5 100644 --- a/Tesses.CrossLang.PackageServer/src/program.tcross +++ b/Tesses.CrossLang.PackageServer/src/program.tcross @@ -243,6 +243,23 @@ func main(args) }); return true; } + if(ctx.Path == "/delete_packages") + { + if(ctx.Method == "GET") + { + ctx.WithMimeType("text/html").SendText(Pages.DeletePackages(ctx)); + return true; + } + else if(ctx.Method == "POST") + { + var packages = ctx.QueryParams.TryGetFirst("packages"); + var email = ctx.QueryParams.TryGetFirst("email"); + var password = ctx.QueryParams.TryGetFirst("password"); + var msg = DB.DeletePackages(email,password, packages); + var html =

{msg}

; + ctx.WithMimeType("text/html").SendText(Shell(msg,[], html)); + } + } if(ctx.Path == "/api/v1/upload") { if(ctx.Method == "PUT")