Skip to content

Instantly share code, notes, and snippets.

View xperiandri's full-sized avatar

Andrii Chebukin xperiandri

View GitHub Profile
type IServiceCollection with
// HACK:
member services.AddAuthorizationWithReflection (configure) =
let name = "Microsoft.Extensions.DependencyInjection.AuthorizationServiceCollectionExtensions, " +
"Microsoft.AspNetCore.Authorization, Version=2.1"
let ``type`` = Type.GetType name
//let private addAuthorization = ``type``.GetMethod("AddAuthorization", BindingFlags.Public ||| BindingFlags.Static,
[| typeof<IServiceCollection>; typeof<Action<AuthorizationOptions>> |])
let addAuthorization = ``type``.GetMethods().[1]
let GrupoMutationsType =
Define.Object<GrupoArgs>
(name = "GrupoMutations", description = "Group mutations",
fields =
[ Define.PatchesField("patch", PatchCacheKey,
// Attach policy / Цепляем политику
GrupoPatchMutations).WithAuthorizationPolicies<GrupoPatchViewModel> (Policies.GroupAdmin)
(Define.AsyncUnitResultField
("addAdmin", "Add group admin (any admin can do)",
type WebJobsHttpExtensionStartup () =
interface IWebJobsStartup with
member __.Configure (builder : IWebJobsBuilder) =
builder.Services
.AddScoped<Lazy<Result<GraphQLUser, Errors.ErrorMessage>>>(
fun provider -> Control.Lazy.Create(fun () -> WebJobsHttpExtensionStartup.GetUserIdResultFromClaims provider))
.AddAuthorizationWithReflection (fun options ->
options.AddPolicy(Policies.EditBooks,
type AllowedGroupRequierment (groups : string seq) =
member val Groups = groups.ToImmutableHashSet ()
interface IAuthorizationRequirement
type AllowedGroupHandler (graphService : IMicrosoftGraphService, userIdResult : Lazy<Result<GraphQLUser, Errors.ErrorMessage>>) =
inherit AuthorizationHandler<AllowedGroupRequierment> ()
override _.HandleRequirementAsync (context, requirement) = task {
match userIdResult.Value with
| Result.Error _ -> return () // user not authenticated / пользователь не аутентифицирован
let handleRequest (serviceProvider : IServiceProvider) (requestBodyStream : Stream) = async {
...
try
...
let! result =
match request with
| ValueSome (query, ValueSome variables) ->
async {
let query = removeWhitespacesAndLineBreaks query
let root = serviceProvider.GetRequiredService<Root>()
// F#
type public GraphQLFunction (serviceProvider : IServiceProvider, log : ILogger<GraphQLFunction>) =
[<FunctionName "GraphQL">]
member public __.Execute
([<HttpTrigger(AuthorizationLevel.Anonymous, "POST", Route = null)>] req : HttpRequest,
cancellationToken : CancellationToken) = Async.StartAsTask (async {
let! responseData = GraphQL.handleRequest serviceProvider req.Body
let responseBody = GraphQLFunction.GetBody log responseData
mutation grupo ($id: GrupoID!, $patchOperations: [JsonPatchOperation!]) {
grupo (id: $id) {
patch (operations: $patchOperations)
}
}
let JSONPatchOperationInputType<'t when 't : not struct> =
let name = sprintf "Input%s_JSON_PatchOperation" (typeof<'t>.Name.Replace ("ViewModel", System.String.Empty))
Define.InputObject<Operation<'t>>
mutation grupo ($id: GrupoID!
$name: GrupoName!
$description: String
$imageURL: GrupoImageURL!) {
grupo (id: $id) {
// Intercept AST and handle its processing / Перехватываем AST и обрабаываем сами
patch {
description (description: $description) // return null or error for field / возвращаем null или ошибку по полю
mutation grupo ($id: GrupoID!
$addAdminCommand: AddAdminCommand!
$name: GrupoName!
$description: String
$imageURL: GrupoImageURL!
$removeAdminCommand: RemoveAdminCommand!) {
grupo (id: $id) {
addAdmin (addAdminCommand: $addAdminCommand) // in parallel / параллельно
mutation grupo ($id: GrupoID!, $addAdminCommand: AddAdminCommand!, $description: String, $imageURL: GrupoImageURL!, $name: GrupoName!, $removeAdminCommand: RemoveAdminCommand!) {
grupo_addAdmin (id: $id, addAdminCommand: $addAdminCommand)
grupo_delete (id: $id)
grupo_join (id: $id)
grupo_leave (id: $id)
grupo_patch (id: $id) {
description (description: $description)
imageURL (imageURL: $imageURL)
name (name: $name)