1 /** 2 * Methods to generate `security.d`, allowing the client to use the security schemes in the OpenAPI 3 * Specification. 4 */ 5 module openapi_client.security; 6 7 import std.array : appender, split, Appender; 8 import std.file : mkdir, mkdirRecurse, write; 9 import std.path : buildNormalizedPath, dirName; 10 import std.string : tr; 11 import std.stdio : writeln; 12 13 import openapi : OasDocument, OasServer, OasServerVariable, OasSecurityScheme; 14 import openapi_client.util : wordWrapText, toUpperCamelCase; 15 16 17 /** 18 * Writes a utility class containing information about the REST API servers to contact. 19 */ 20 void writeSecurityFiles(OasDocument oasDocument, string targetDir, string packageRoot) { 21 auto buffer = appender!string(); 22 string moduleName = packageRoot ~ ".security"; 23 with (buffer) { 24 put("// File automatically generated from OpenAPI spec.\n"); 25 put("module " ~ moduleName ~ ";\n"); 26 put("\n"); 27 put("import openapi_client.apirequest : ApiRequest;\n"); 28 put("import openapi;\n"); 29 put("\n"); 30 put("import std.base64 : Base64;\n"); 31 put("import std.conv : to;\n"); 32 put("import std.array : Appender;\n"); 33 put("\n"); 34 put("class Security {\n\n"); 35 put(" /**\n"); 36 put(" * The currently active security method to be applied to requests.\n"); 37 put(" */\n"); 38 put(" static void delegate(ApiRequest) applySecurityF = null;\n\n"); 39 foreach (string securitySchemeName, OasSecurityScheme securityScheme; 40 oasDocument.components.securitySchemes) { 41 if (securityScheme.type == "http") { 42 if (securityScheme.scheme == "basic") { 43 put(" /**\n"); 44 put(" * Enable and configure the use of HTTP Basic Authentication.\n"); 45 put(" *\n"); 46 put(" * See_Also: https://en.wikipedia.org/wiki/Basic_access_authentication\n"); 47 put(" */\n"); 48 put(" static void configure" ~ toUpperCamelCase(securitySchemeName) 49 ~ "(string username, string password) {\n"); 50 put(" applySecurityF = (ApiRequest request) {\n"); 51 put(" auto buffer = new Appender!string();\n"); 52 put(" auto credentials = cast(immutable(ubyte)[])(username ~ \":\" ~ password);\n"); 53 put(" Base64.encode(credentials, buffer);\n"); 54 put(" request.setHeaderParam(\"Authorization\", \"Basic \" ~ buffer.data);\n"); 55 put(" };\n"); 56 put(" }\n\n"); 57 } else if (securityScheme.scheme == "bearer") { 58 put(" /**\n"); 59 put(" * Enable and configure the use of an OAuth2.0 Bearer token for HTTP Authentication.\n"); 60 put(" *\n"); 61 put(" * See_Also: https://datatracker.ietf.org/doc/html/rfc6750\n"); 62 put(" */\n"); 63 put(" static void configure" ~ toUpperCamelCase(securitySchemeName) 64 ~ "(string token) {\n"); 65 put(" applySecurityF = (ApiRequest request) {\n"); 66 put(" request.setHeaderParam(\"Authorization\", \"Bearer \" ~ token);\n"); 67 put(" };\n"); 68 put(" }\n\n"); 69 } else { 70 writeln("Warning: Unsupported security scheme type=http, scheme=", securityScheme.scheme); 71 } 72 } else { 73 writeln("Warning: Unsupported security scheme type '", securityScheme.type, "'."); 74 } 75 } 76 put(" /**\n"); 77 put(" * Apply the currently selected security method to a request.\n"); 78 put(" */\n"); 79 put(" static void apply(ApiRequest request) {\n"); 80 put(" if (applySecurityF !is null)\n"); 81 put(" applySecurityF(request);\n"); 82 put(" }\n\n"); 83 put("}\n"); 84 } 85 string fileName = buildNormalizedPath(targetDir, tr(moduleName, ".", "/") ~ ".d"); 86 mkdirRecurse(dirName(fileName)); 87 write(fileName, buffer[]); 88 }