Clockify- CreateProjectAsync with Memberships - clockify

I'm having a error when I use c# API clockify
When I create a Project with Memberships I get this error:
"{\"message\":\"Internal server error.\",\"code\":500}"
When i comment Memberships attribute the project it's created.
var assignees = new List<MembershipRequest>();
var member = new MembershipRequest();
member.MembershipStatus = MembershipStatus.Active;
member.MembershipType = "PROJECT";
member.UserId = "UserId";
assignees.Add(member);
var project = new ProjectRequest
{
Name = "ProjetName",
ClientId = "ClienteID",
IsPublic = false,
Billable = true,
Color = "#000000",
Memberships = assignees
};
var clockify = new ClockifyClient("APIKey");
var response = await clockify.CreateProjectAsync("WorkSpaceID", project).ConfigureAwait(true);

Memberships are a nested object.
So if it would work, the code would be
{
Name = "ProjetName",
ClientId = "ClienteID",
IsPublic = false,
Billable = true,
Color = "#000000",
"memberships": [{
"userId": assignee
}]
}
However this is not included in the endpoint, so what I did to make this work was:
PATCH /workspaces/{workspaceId}/projects/{projectId}/memberships
{
"memberships": [
{
"userId": assignee
}
]
}

Related

No service for type 'IdentityServer4.Configuration.IdentityServerOptions' has been registered. - Mocking HttpContext.SignInAsync

I'm trying to cover External auth with Unit Tests.
Mocked all dependencies including SignInAsync(). But execution fails with the message "No service for type 'IdentityServer4.Configuration.IdentityServerOptions' has been registered." when it hits SignInAsync().
Stack trace here
Test method.
public async Task CallBack_User_Is_Defined_In_AAD_ReturnChallenge()
{
var ticket = new AuthenticationTicket(TestUsers.Principal, "Test");
var result = AuthenticateResult.Success(ticket);
result.Properties?.Items.Add("returnUrl", "sign-callback");
result.Properties?.Items.Add("scheme", "aad");
authenticationService.Setup(c => c.AuthenticateAsync(It.IsAny<HttpContext>(), IdentityServerConstants.ExternalCookieAuthenticationScheme)).Returns(Task.FromResult(result)); ;
var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock
.Setup(_ => _.GetService(typeof(IAuthenticationService)))
.Returns(authenticationService.Object);
serviceProviderMock
.Setup(_ => _.GetService(typeof(IdentityOptions)))
.Returns(authenticationService.Object);
var identityServiceUserResponse = new IdentityServiceUserResponse
{
Email = TestUsers.Principal.FindFirstValue(ClaimTypes.Email),
CompanyID = "1",
Login = "john"
};
identityServiceAuthService.Setup(c => c.GetUserByExternalEmailAsync(It.IsAny<string>()))
.Returns(Task.FromResult(identityServiceUserResponse));
var authRequest = new AuthorizationRequest
{
Client = new Client { ClientId = "client" },
ValidatedResources = resourceValidationResult,
Parameters = { { "returnUrl", "signin-callback" } },
};
interactionService.Setup(i => i.GetAuthorizationContextAsync(It.IsAny<string>()))
.Returns(Task.FromResult(authRequest));
authenticationService
.Setup(_ => _.SignInAsync(It.IsAny<HttpContext>(), It.IsAny<string>(), It.IsAny<ClaimsPrincipal>(), It.IsAny<AuthenticationProperties>()))
.Returns(Task.FromResult((object)null));
controller = new ExternalController(configuration.Object, interactionService.Object,
identityServiceAuthService.Object, clientStore.Object, events.Object, logger.Object);
controller.ControllerContext = controller.CreateControllerContext(TestUsers.Principal);
controller.ControllerContext.HttpContext.RequestServices = serviceProviderMock.Object;
await controller.Callback();
}

Azure Cosmos DB SQL API-Encryption-failed on loading documents

We have been trying to implement the encryption in Cosmos DB as per the below documentation
https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-always-encrypted?tabs=dotnet
We have been able to create the database with the encryption techniques and also the fields. Below is the code used
var databaseClient = cosmosClient.GetDatabase(createSqlIndexRequest.DatabaseName);
await databaseClient.CreateClientEncryptionKeyAsync(
keyName,
DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256,
new EncryptionKeyWrapMetadata(
keyWrapProvider.ProviderName,
keyName,
keyVaultIdentifier));
var fieldEncryptionPathList = new List<ClientEncryptionIncludedPath>();
foreach (var fieldEncryptItem in createSqlIndexRequest.FieldNamesForEncryption)
{
fieldEncryptionPathList.Add(new ClientEncryptionIncludedPath()
{
Path = $"/{fieldEncryptItem}",
ClientEncryptionKeyId = keyName,
EncryptionType = EncryptionType.Deterministic.ToString(),
EncryptionAlgorithm = DataEncryptionKeyAlgorithm.AeadAes256CbcHmacSha256
});
}
ContainerProperties containerProperties = new ContainerProperties
{
PartitionKeyPath = createSqlIndexRequest.PartitionKey,
Id = createSqlIndexRequest.CollectionName,
ClientEncryptionPolicy = new ClientEncryptionPolicy(fieldEncryptionPathList),
IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy()
{
IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.None,
Automatic = false
}
};
var containerCheck = await databaseClient.CreateContainerIfNotExistsAsync(containerProperties, ruLevel.HasValue && !ruLevel.Value ? ruValue : null);
Once the above code runs, we can see the database and container created successfully.
We are trying to insert Documents using the DATA Explorer available in Azure Portal, a sample one
{
"id": "1234",
"job_id": 122,
"job_name": "mongo_cosmos_job",
"job_type": "onetimeDataOffload",
"source_connector_id": 98.0,
"source_connector_name": "mongo_src",
"source_type": "mongo",
"source_database": "company",
"destination_connector_id": 99.0,
"destination_connector_name": "cosmosmongo_serverless_dest",
"destination_type": "cosmos",
"destination_database": "mongo_cosmos_db",
"dag_run_id": "manual__2021-10-06T09:56:07.175777+00:00",
"task_id": "extract_and_load_company.test_collection",
"task_name": "extract_and_load_company.test_collection",
"table_name": "test_collection",
"stage": "load",
"record_count": 0,
"size_in_mb": 0.0,
"duration": 0.0,
"is_aggregated": false,
"is_test_dag": false,
"chunk_size": 5000.0,
"ru_level": "",
"ru": 0.0,
"job_execution_datetime": "2021-10-06 09:56:07.177",
"task_execution_datetime": "2021-10-06 09:56:07.177",
"job_status": "success",
"task_execution_endtime": "2021-10-06 09:56:42.650"
}
on click of Save, we get the following error
AzureCosmosDB Encryption Document Insert Error
The error message is as follows
the collection has ClientEncryptionPolicy set, but the document to be written isn't encrypted.
please help us in resolving the issue.

How to add multiple actions to Swashbuckle Document Path pointing to one endpoint?

I try to describe my asp.net Web API OAuth endpoint in swagger using Swashbuckle 5.6.0 and tried this solution:
How to show WebApi OAuth token endpoint in Swagger
My problem is, that the URL of receiving an access token and getting a new one by refresh token is the same in asp.net OAuth Authorization Server.
Adding the second URL to the Swagger Document Path fails due to the fact, that "paths" is a IDictionary<string, PathItem>.
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
// get the Token Endpoint from Config
var endpoint = Helpers.GetAppSetting("TokenEndPoint");
// Access Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
}
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint, new PathItem
{
post = new Operation
{
tags = new List<string> { "AccessToken" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
#in = "formData"
}
}
}
});
}
}
Is there any possibility to describe two api methods pointing to the same endpoint, just using diffrent parameters?
Like shown here: https://api.gettyimages.com/swagger/ui/index#!/OAuth
Finally the hint "adding something meaningless" worked for our use case.
I additionally added a new model class AuthServerResponseModel, where the response of the auth request is mapped in.
public class AuthServerResponseModel
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string refresh_token { get; set; }
public string audience { get; set; }
}
To make this object be known in Swagger, the class has to be added to the SchemaRegistry.
After that I could use the "#ref" tag in the response schema to declare the response type of my auth request.
public class AuthTokenOperation : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
schemaRegistry.GetOrRegister(typeof(AuthServerResponseModel));
// get the Token Endpoint from Config
string endpoint = "URL-To-The-OAuth-Endpoint";
// Access Token
swaggerDoc.paths.Add(endpoint + "#AccessToken", new PathItem
{
post = new Operation
{
operationId = "AccessToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "username",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "password",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "DeviceId",
required = false,
#in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", #ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
// Refresh Token
swaggerDoc.paths.Add(endpoint + "#RefreshToken", new PathItem
{
post = new Operation
{
operationId = "RefreshToken",
tags = new List<string> { "Token" },
consumes = new string[] { "application/x-www-form-url-encoded" },
produces = new string[] { "application/json" },
parameters = new List<Parameter>
{
new Parameter
{
type = "string",
name = "grant_type",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_id",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "client_secret",
required = true,
#in = "formData"
},
new Parameter
{
type = "string",
name = "refresh_token",
required = true,
#in = "formData"
}
},
responses = new Dictionary<string, Response>()
{
{ "200", new Response() { description = "Ok", schema = new Schema() { type = "object", #ref = "#/definitions/AuthServerResponseModel" } } },
{ "400", new Response() { description = "BadRequest" } },
{ "404", new Response() { description = "NotFound" } }
}
}
});
}
}
Automatic Client generation using Swagger Codegen works well now.
The paths is a dictionary in swashbuckle:
public class SwaggerDocument
{
public readonly string swagger = "2.0";
public Info info;
...
public IDictionary<string, PathItem> paths;
...
}
that is why the exception "key has already been added to the collection"
On swagger we follow the Open Api Specification, and that path is a patterned field:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#patterned-fields
And they clearly state that duplicates is a no no for those patterned fields:
Patterned fields can have multiple occurrences as long as each has a unique name.
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#specification
The best option is to append something meaningless (like hash) to the endpoints to make them different, it could be something like:
swaggerDoc.paths.Add(endpoint + "#Access", new PathItem ...
swaggerDoc.paths.Add(endpoint + "#Refresh", new PathItem ...
How are the guys at gettyimages getting around that?
Here are some interesting findings
Their swagger json does not have those /oauth2/token paths
you can double check directly here:
https://api.gettyimages.com/swagger/docs/3
Here is how their swagger json looks like in the latest version of the swagger-ui:
http://petstore.swagger.io/?defaultModelsExpandDepth=0&docExpansion=none&url=https://api.gettyimages.com/swagger/docs/3
The version of swagger-ui they are using at gettyimages is heavily customized, I think they are injecting additional paths using JS
https://api.gettyimages.com/swagger/ui/ext/GettyImages-Resources-OAuthGrant-js
You can do that too, it will be a lot more work than just appending something to the endpoints

DynamoDB Query confusion

I have the following table creation code for DynamoDB (C#):
client.CreateTable(new CreateTableRequest
{
TableName = tableName,
ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 20, WriteCapacityUnits = 10 },
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "RID",
KeyType = KeyType.HASH
}
}
,
AttributeDefinitions = new List<AttributeDefinition>
{
new AttributeDefinition {
AttributeName = "RID",
AttributeType = ScalarAttributeType.N
}
}
});
the data that gets populated into this table comes from this JSON:
[
{"RID": 208649, "CLI_RID": 935476, "PRT_DT": "VAL_AA", "DISTR": "INTERNAL"},
{"RID": 217427, "CLI_RID": 1009561, "PRT_DT": "VAL_BB", "DISTR": "INTERNAL", "STATE": "VAL_BD"},
{"RID": 223331, "CLI_RID": 1325477, "PRT_DT": "VAL_CB", "DISTR": "", "STATE": "VAL_CD", "FNAME": "VAL_CE", "START": "VAL_CF"},
{"RID": 227717, "CLI_RID": 1023478, "PRT_DT": "VAL_DB", "DISTR": "", "STATE": "VAL_DD"}
{"RID": 217462, "CLI_RID": 1009561, "PRT_DT": "VAL_BB", "DISTR": "", "STATE": "VAL_BD"},
{"RID": 218679, "CLI_RID": 1009561, "PRT_DT": "VAL_AA", "DISTR": "INTERNAL"},
{"RID": 222376, "CLI_RID": 1263978, "PRT_DT": "VAL_DB", "DISTR": "", "STATE": "VAL_DD"}
]
How would I Query or Filter for all records containing 1009561 in column "CLI_RID" and column "DISTR" <> "INTERNAL"?
There will be about 15 mil records in this DynamoDB table.
Is my table defined correctly for this query/filter?
Updated table creation:
// CLI_RIDIndex
var cli_ridIndex = new GlobalSecondaryIndex
{
IndexName = "cli_ridIndex",
ProvisionedThroughput = new ProvisionedThroughput
{
ReadCapacityUnits = 20,
WriteCapacityUnits = 10
},
KeySchema = {
new KeySchemaElement
{
AttributeName = "CLI_RID", KeyType = "HASH"
}
},
Projection = new Projection { ProjectionType = "ALL" }
};
client.CreateTable(new CreateTableRequest
{
TableName = tableName,
ProvisionedThroughput = new ProvisionedThroughput { ReadCapacityUnits = 20, WriteCapacityUnits = 10 },
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement
{
AttributeName = "RID",
KeyType = KeyType.HASH // Partiton Key (Unique)
},
new KeySchemaElement
{
AttributeName = "CLI_RID",
KeyType = KeyType.RANGE // Sort Key
}
}
,
AttributeDefinitions = new List<AttributeDefinition>
{
new AttributeDefinition {
AttributeName = "RID",
AttributeType = ScalarAttributeType.N
},
new AttributeDefinition {
AttributeName = "CLI_RID",
AttributeType = ScalarAttributeType.N
}
},
GlobalSecondaryIndexes = { cli_ridIndex }
});
But when attempting to query it,
var request = new QueryRequest
{
TableName = "TNAArchive",
KeyConditionExpression = "CLI_RID = :v_cli_rid",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_cli_rid", new AttributeValue { S = "905466" }}}
};
var response = client.Query(request);
I get this error:
Query condition missed key schema element: RID
I guess I'm not really understanding how to do this.
According to your table structure, you won't be able to perform Query on the table but you have to Scan it which we need to avoid.
To perform Query you need to modify certain things
1) Add a Global Secondary Index(GSI) with the field CLI_RID as Hash
2) Now You Query GSI by passing CLI_RID and add query filter with condition <> your value
Here is the reference link.
Edit: Your Main table structure will be same no need to change, but you need to add one more GSI with Hash key as CLI_RID and project required table attribute.
Now you need to query your GSI instead of the table with a hash key as CLI_RID, you don't need to pass RID here.
here is the link on how to add GSI on table.
If CLI_RID is not present in a master table then that record will not be reflected in the GSI so no need to worry.
Edit 2: Just add (IndexName = NameOFYourIndex) attribute while querying and everything should work.
var request = new QueryRequest
{
TableName = "TNAArchive",
IndexName = "NameOfYourIndex",
KeyConditionExpression = "CLI_RID = :v_cli_rid",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":v_cli_rid", new AttributeValue { S = "905466" }}}
};
Hope that helps

Get child structure groups given a structure group TCM URI with Core Service

How can I get all child structure groups given a structure group TCM URI with Core Service?
I tried using this code:
ItemsFilterData sgFilter = new RepositoryItemsFilterData
{ ItemTypes = new[] { ItemType.StructureGroup },
Recursive = true,
BaseColumns = ListBaseColumns.Id };
XElement listXml;
using (CoreServiceClient client = _coreServiceProvider.GetCoreServiceClient())
{
listXml = XElement.Parse(
client.ProxyClient.GetListXml(structureGroupUri, sgFilter)
.OuterXml);
}
But I got an error saying "Unexpected item type: StructureGroup".
Starting from the Publication's URI, this works:
client.GetListXml("tcm:0-10-1", new RepositoryItemsFilterData {
ItemTypes = new[] { ItemType.StructureGroup },
Recursive = true,
BaseColumns = ListBaseColumns.Id
})
The trick is always to find the correct filter type, which in this case is RepositoryItemsFilterData.
Non-working sample
Starting from the Structure Group's URI, this returns the direct children Structure Groups. Note that that Recursive = true seems to be ignored here.
client.GetListXml("tcm:10-328-4", new OrganizationalItemItemsFilterData {
ItemTypes = new[] { ItemType.StructureGroup },
Recursive = true,
BaseColumns = ListBaseColumns.Id
})

Resources