public Users(string dbUrl, string storageDir, string masterPassword) : base(dbUrl) { this.dbUrl = dbUrl; this.masterPassword = masterPassword; var avatarDir = Path.Combine(storageDir, "avatar"); if (!Dir.Exists(avatarDir)) { Dir.CreateDirectory(avatarDir); } // API only available to authenticated users BeforeAsync = async(p, c) => await c.EnsureIsAuthenticatedAsync(); // register a type Types["uid"] = (val) => (Regex.IsMatch(val, "^[A-Z0-9]+$")) ? val : null; GetAsync["/"] = async(p, c) => { await RunBeforeAsync(null, c); var authUser = await c.GetAuthenticatedUserAsync(); SqlFilter filterAuth; if (authUser.IsUser && c.Request.QueryString.ContainsKey("restrict")) { filterAuth = User.GenerateFilterAuthUser(authUser); } else { filterAuth = (new User()).FilterAuthUser(authUser); } using (DB db = await DB.CreateAsync(dbUrl)) { var result = await Model.SearchAsync <User>(db, c, filterAuth); foreach (var item in result.Data) { await item.EnsureRightAsync(c, Right.Read, null); } c.Response.Content = result.ToJson(c); } c.Response.StatusCode = 200; }; GetAsync["/current"] = async(p, c) => { var user = await c.GetAuthenticatedUserAsync(); if ((user == null) || !user.IsUser) { c.Response.StatusCode = 401; } else { c.Response.StatusCode = 302; c.Response.Headers["location"] = user.user.id; } }; GetAsync["/current/isauthenticated"] = async(p, c) => { var user = await c.GetAuthenticatedUserAsync(); if (user == null) { c.Response.StatusCode = 403; } else { c.Response.StatusCode = 200; } }; PostAsync["/{uid:uid}/upload/avatar"] = async(p, c) => { var uid = (string)p["uid"]; var oldUser = new User { id = uid }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldUser.LoadAsync(db, true)) { oldUser = null; } } //var oldUser = await GetUserAsync(uid); if (oldUser == null) { return; } await c.EnsureHasRightsOnUserAsync(oldUser, true, true, false); var reader = c.Request.ReadAsMultipart(); MultipartPart part; while ((part = await reader.ReadPartAsync()) != null) { if (part.Headers.ContainsKey("content-disposition") && part.Headers.ContainsKey("content-type")) { if ((part.Headers["content-type"] != "image/jpeg") && (part.Headers["content-type"] != "image/png") && (part.Headers["content-type"] != "image/svg+xml")) { continue; } var disposition = ContentDisposition.Decode(part.Headers["content-disposition"]); if (disposition.ContainsKey("name") && (disposition["name"] == "image")) { var dir = DirExt.CreateRecursive(Path.Combine( avatarDir, uid[0].ToString(), uid[1].ToString(), uid[2].ToString())); var ext = ".jpg"; var format = "jpeg"; //if ((part.Headers["content-type"] == "image/png") || (part.Headers["content-type"] == "image/svg+xml")) //{ // ext = ".png"; // format = "png"; //} var name = StringExt.RandomString(16) + "_" + uid + ext; // crop / resize / convert the image using ImageMagick var startInfo = new ProcessStartInfo("/usr/bin/convert", "- -auto-orient -strip -set option:distort:viewport \"%[fx:min(w,h)]x%[fx:min(w,h)]+%[fx:max((w-h)/2,0)]+%[fx:max((h-w)/2,0)]\" -distort SRT 0 +repage -quality 80 -resize 256x256 " + format + ":" + Path.Combine(dir.FullName, name)); startInfo.RedirectStandardOutput = false; startInfo.RedirectStandardInput = true; startInfo.UseShellExecute = false; var process = new Process(); process.StartInfo = startInfo; process.Start(); // read the file stream and send it to ImageMagick await part.Stream.CopyToAsync(process.StandardInput.BaseStream); process.StandardInput.Close(); process.WaitForExit(); process.Dispose(); c.Response.StatusCode = 200; var userDiff = new User { id = uid, avatar = name }; using (DB db = await DB.CreateAsync(dbUrl)) { await userDiff.UpdateAsync(db); await userDiff.LoadAsync(db, true); } c.Response.Content = userDiff; if ((oldUser.avatar != null) && (oldUser.avatar != "empty")) { var oldFile = Path.Combine(avatarDir, uid[0].ToString(), uid[1].ToString(), uid[2].ToString(), Path.GetFileName(oldUser.avatar)); if (File.Exists(oldFile)) { File.Delete(oldFile); } } } } } }; GetAsync["/{uid:uid}/avatar"] = async(p, c) => { var uid = (string)p["uid"]; var user = new User { id = uid }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await user.LoadAsync(db, true)) { user = null; } } if (user == null) { return; } string avatarPath; if ((user.avatar == null) || (user.avatar == "empty")) { if (user.gender == null) { avatarPath = "/avatar/avatar_neutre.svg"; } else if (user.gender == Gender.M) { avatarPath = "/avatar/avatar_masculin.svg"; } else { avatarPath = "/avatar/avatar_feminin.svg"; } } else { avatarPath = "/api/avatar/user/" + uid.Substring(0, 1) + "/" + uid.Substring(1, 1) + "/" + uid.Substring(2, 1) + "/" + user.avatar; } c.Response.StatusCode = 302; c.Response.Headers["location"] = avatarPath; }; }
public Structures(string dbUrl, string storageDir) : base(dbUrl) { var structureDir = Path.Combine(storageDir, "structure"); if (!Dir.Exists(structureDir)) { Dir.CreateDirectory(structureDir); } // API only available to authenticated users BeforeAsync = async(p, c) => await c.EnsureIsAuthenticatedAsync(); GetAsync["/{id}/subjects"] = async(p, c) => { c.Response.StatusCode = 200; using (DB db = await DB.CreateAsync(dbUrl)) c.Response.Content = await db.SelectAsync <Grade>("SELECT * FROM subject WHERE id IN (SELECT `subject_id` FROM `group_user` WHERE `group_id` IN (SELECT id FROM `group` WHERE `structure_id`=?))", (string)p["id"]); }; GetAsync["/{id}/image"] = async(p, c) => { var id = (string)p["id"]; var oldStructure = new Structure { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldStructure.LoadAsync(db, true)) { oldStructure = null; } } if (oldStructure == null) { return; } var fullPath = Path.Combine(structureDir, $"{id}.jpg"); if (File.Exists(fullPath)) { var shortName = Path.GetFileName(fullPath); c.Response.Headers["content-type"] = "image/jpeg"; var lastModif = File.GetLastWriteTime(fullPath); string etag = "\"" + lastModif.Ticks.ToString("X") + "\""; c.Response.Headers["etag"] = etag; if (c.Request.QueryString.ContainsKey("if-none-match") && (c.Request.QueryString["if-none-match"] == etag)) { c.Response.StatusCode = 304; } else { c.Response.StatusCode = 200; c.Response.SupportRanges = true; c.Response.Content = new FileContent(fullPath); } } }; DeleteAsync["/{id}/image"] = async(p, c) => { var id = (string)p["id"]; var oldStructure = new Structure { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldStructure.LoadAsync(db, true)) { oldStructure = null; } } if (oldStructure == null) { return; } await c.EnsureHasRightsOnStructureAsync(oldStructure, false, false, true); var fullPath = Path.Combine(structureDir, $"{id}.jpg"); if (File.Exists(fullPath)) { File.Delete(fullPath); c.Response.StatusCode = 200; c.Response.Content = ""; } }; PostAsync["/{id}/image"] = async(p, c) => { var id = (string)p["id"]; var oldStructure = new Structure { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldStructure.LoadAsync(db, true)) { oldStructure = null; } } if (oldStructure == null) { return; } await c.EnsureHasRightsOnStructureAsync(oldStructure, false, false, true); var reader = c.Request.ReadAsMultipart(); MultipartPart part; while ((part = await reader.ReadPartAsync()) != null) { if (part.Headers.ContainsKey("content-disposition") && part.Headers.ContainsKey("content-type")) { if ((part.Headers["content-type"] != "image/jpeg") && (part.Headers["content-type"] != "image/png") && (part.Headers["content-type"] != "image/svg+xml")) { continue; } var disposition = ContentDisposition.Decode(part.Headers["content-disposition"]); if (disposition.ContainsKey("name") && (disposition["name"] == "image")) { var dir = DirExt.CreateRecursive(structureDir); var fullPath = Path.Combine(dir.FullName, $"{id}.jpg"); // crop / resize / convert the image using ImageMagick var startInfo = new ProcessStartInfo("/usr/bin/convert", $"- -auto-orient -strip -distort SRT 0 +repage -quality 80 -resize 1024x1024 jpeg:{fullPath}"); startInfo.RedirectStandardOutput = false; startInfo.RedirectStandardInput = true; startInfo.UseShellExecute = false; var process = new Process(); process.StartInfo = startInfo; process.Start(); // read the file stream and send it to ImageMagick await part.Stream.CopyToAsync(process.StandardInput.BaseStream); process.StandardInput.Close(); process.WaitForExit(); process.Dispose(); c.Response.StatusCode = 200; } } } }; }
public Resources(string dbUrl, string storageDir) : base(dbUrl) { var resourceDir = Path.Combine(storageDir, "resource"); if (!Dir.Exists(resourceDir)) { Dir.CreateDirectory(resourceDir); } GetAsync["/{id:int}/image"] = async(p, c) => { var id = (int)p["id"]; var oldResource = new Resource { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldResource.LoadAsync(db, true)) { oldResource = null; } } if (oldResource == null) { return; } var fullPath = Path.Combine(resourceDir, $"{id}.jpg"); if (File.Exists(fullPath)) { var shortName = Path.GetFileName(fullPath); c.Response.Headers["content-type"] = "image/jpeg"; var lastModif = File.GetLastWriteTime(fullPath); string etag = "\"" + lastModif.Ticks.ToString("X") + "\""; c.Response.Headers["etag"] = etag; if (c.Request.QueryString.ContainsKey("if-none-match") && (c.Request.QueryString["if-none-match"] == etag)) { c.Response.StatusCode = 304; } else { c.Response.StatusCode = 200; c.Response.SupportRanges = true; c.Response.Content = new FileContent(fullPath); } } }; DeleteAsync["/{id:int}/image"] = async(p, c) => { var id = (int)p["id"]; var oldResource = new Resource { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldResource.LoadAsync(db, true)) { oldResource = null; } } if (oldResource == null) { return; } var fullPath = Path.Combine(resourceDir, $"{id}.jpg"); if (File.Exists(fullPath)) { File.Delete(fullPath); c.Response.StatusCode = 200; c.Response.Content = ""; } }; PostAsync["/{id:int}/image"] = async(p, c) => { var id = (int)p["id"]; var oldResource = new Resource { id = id }; using (var db = await DB.CreateAsync(dbUrl)) { if (!await oldResource.LoadAsync(db, true)) { oldResource = null; } } if (oldResource == null) { return; } var reader = c.Request.ReadAsMultipart(); MultipartPart part; while ((part = await reader.ReadPartAsync()) != null) { if (part.Headers.ContainsKey("content-disposition") && part.Headers.ContainsKey("content-type")) { if ((part.Headers["content-type"] != "image/jpeg") && (part.Headers["content-type"] != "image/png") && (part.Headers["content-type"] != "image/svg+xml")) { continue; } var disposition = ContentDisposition.Decode(part.Headers["content-disposition"]); if (disposition.ContainsKey("name") && (disposition["name"] == "image")) { var dir = DirExt.CreateRecursive(resourceDir); var fullPath = Path.Combine(dir.FullName, $"{id}.jpg"); // crop / resize / convert the image using ImageMagick var startInfo = new ProcessStartInfo("/usr/bin/convert", $"- -auto-orient -strip -distort SRT 0 +repage -quality 80 -resize 1024x1024 jpeg:{fullPath}"); startInfo.RedirectStandardOutput = false; startInfo.RedirectStandardInput = true; startInfo.UseShellExecute = false; var process = new Process(); process.StartInfo = startInfo; process.Start(); // read the file stream and send it to ImageMagick await part.Stream.CopyToAsync(process.StandardInput.BaseStream); process.StandardInput.Close(); process.WaitForExit(); process.Dispose(); c.Response.StatusCode = 200; } } } }; }