Changing Password is functional through API and Client

This commit is contained in:
Daniel Schick 2023-08-18 15:29:20 +02:00
parent 083ea69961
commit 411ea8135e
11 changed files with 1208 additions and 678 deletions

View File

@ -1,7 +1,7 @@
//---------------------- //----------------------
// <auto-generated> // <auto-generated>
// Generated REST API Client Code Generator v1.7.17.0 on 17.08.2023 10:11:31 // Generated REST API Client Code Generator v1.7.17.0 on 18.08.2023 15:15:15
// Using the tool OpenAPI Generator v6.6.0 // Using the tool OpenAPI Generator v6.6.0
// </auto-generated> // </auto-generated>
//---------------------- //----------------------
@ -280,6 +280,25 @@ namespace BreCalClient.misc.Api
/// <param name="operationIndex">Index associated with the operation.</param> /// <param name="operationIndex">Index associated with the operation.</param>
/// <returns>ApiResponse of Object(void)</returns> /// <returns>ApiResponse of Object(void)</returns>
ApiResponse<Object> TimesPutWithHttpInfo(Times times, int operationIndex = 0); ApiResponse<Object> TimesPutWithHttpInfo(Times times, int operationIndex = 0);
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <returns></returns>
void UserPut(UserDetails userDetails, int operationIndex = 0);
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <remarks>
///
/// </remarks>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <returns>ApiResponse of Object(void)</returns>
ApiResponse<Object> UserPutWithHttpInfo(UserDetails userDetails, int operationIndex = 0);
#endregion Synchronous Operations #endregion Synchronous Operations
} }
/// <summary> /// <summary>
@ -572,6 +591,30 @@ namespace BreCalClient.misc.Api
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param> /// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
/// <returns>Task of ApiResponse</returns> /// <returns>Task of ApiResponse</returns>
System.Threading.Tasks.Task<ApiResponse<Object>> TimesPutWithHttpInfoAsync(Times times, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); System.Threading.Tasks.Task<ApiResponse<Object>> TimesPutWithHttpInfoAsync(Times times, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <remarks>
///
/// </remarks>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
/// <returns>Task of void</returns>
System.Threading.Tasks.Task UserPutAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <remarks>
///
/// </remarks>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
/// <returns>Task of ApiResponse</returns>
System.Threading.Tasks.Task<ApiResponse<Object>> UserPutWithHttpInfoAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
#endregion Asynchronous Operations #endregion Asynchronous Operations
} }
/// <summary> /// <summary>
@ -2143,6 +2186,134 @@ namespace BreCalClient.misc.Api
} }
return localVarResponse; return localVarResponse;
} }
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <returns></returns>
public void UserPut(UserDetails userDetails, int operationIndex = 0)
{
UserPutWithHttpInfo(userDetails);
}
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <returns>ApiResponse of Object(void)</returns>
public BreCalClient.misc.Client.ApiResponse<Object> UserPutWithHttpInfo(UserDetails userDetails, int operationIndex = 0)
{
// verify the required parameter 'userDetails' is set
if (userDetails == null)
{
throw new BreCalClient.misc.Client.ApiException(400, "Missing required parameter 'userDetails' when calling DefaultApi->UserPut");
}
BreCalClient.misc.Client.RequestOptions localVarRequestOptions = new BreCalClient.misc.Client.RequestOptions();
string[] _contentTypes = new string[] {
"application/json"
};
// to determine the Accept header
string[] _accepts = new string[] {
"application/json"
};
var localVarContentType = BreCalClient.misc.Client.ClientUtils.SelectHeaderContentType(_contentTypes);
if (localVarContentType != null)
{
localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType);
}
var localVarAccept = BreCalClient.misc.Client.ClientUtils.SelectHeaderAccept(_accepts);
if (localVarAccept != null)
{
localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept);
}
localVarRequestOptions.Data = userDetails;
localVarRequestOptions.Operation = "DefaultApi.UserPut";
localVarRequestOptions.OperationIndex = operationIndex;
// authentication (ApiKey) required
if (!string.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("Authorization")))
{
localVarRequestOptions.HeaderParameters.Add("Authorization", this.Configuration.GetApiKeyWithPrefix("Authorization"));
}
// make the HTTP request
var localVarResponse = this.Client.Put<Object>("/user", localVarRequestOptions, this.Configuration);
if (this.ExceptionFactory != null)
{
Exception _exception = this.ExceptionFactory("UserPut", localVarResponse);
if (_exception != null)
{
throw _exception;
}
}
return localVarResponse;
}
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
/// <returns>Task of void</returns>
public async System.Threading.Tasks.Task UserPutAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
await UserPutWithHttpInfoAsync(userDetails, operationIndex, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Update user details (first/last name, phone, password)
/// </summary>
/// <exception cref="BreCalClient.misc.Client.ApiException">Thrown when fails to make API call</exception>
/// <param name="userDetails">User details</param>
/// <param name="operationIndex">Index associated with the operation.</param>
/// <param name="cancellationToken">Cancellation Token to cancel the request.</param>
/// <returns>Task of ApiResponse</returns>
public async System.Threading.Tasks.Task<BreCalClient.misc.Client.ApiResponse<Object>> UserPutWithHttpInfoAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
// verify the required parameter 'userDetails' is set
if (userDetails == null)
{
throw new BreCalClient.misc.Client.ApiException(400, "Missing required parameter 'userDetails' when calling DefaultApi->UserPut");
}
BreCalClient.misc.Client.RequestOptions localVarRequestOptions = new BreCalClient.misc.Client.RequestOptions();
string[] _contentTypes = new string[] {
"application/json"
};
// to determine the Accept header
string[] _accepts = new string[] {
"application/json"
};
var localVarContentType = BreCalClient.misc.Client.ClientUtils.SelectHeaderContentType(_contentTypes);
if (localVarContentType != null)
{
localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType);
}
var localVarAccept = BreCalClient.misc.Client.ClientUtils.SelectHeaderAccept(_accepts);
if (localVarAccept != null)
{
localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept);
}
localVarRequestOptions.Data = userDetails;
localVarRequestOptions.Operation = "DefaultApi.UserPut";
localVarRequestOptions.OperationIndex = operationIndex;
// authentication (ApiKey) required
if (!string.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("Authorization")))
{
localVarRequestOptions.HeaderParameters.Add("Authorization", this.Configuration.GetApiKeyWithPrefix("Authorization"));
}
// make the HTTP request
var localVarResponse = await this.AsynchronousClient.PutAsync<Object>("/user", localVarRequestOptions, this.Configuration, cancellationToken).ConfigureAwait(false);
if (this.ExceptionFactory != null)
{
Exception _exception = this.ExceptionFactory("UserPut", localVarResponse);
if (_exception != null)
{
throw _exception;
}
}
return localVarResponse;
}
} }
} }
@ -7044,3 +7215,189 @@ namespace BreCalClient.misc.Model
} }
} }
/*
* Bremen calling API
*
* Administer DEBRE ship calls, times and notifications
*
* The version of the OpenAPI document: 0.3.0
* Contact: info@textbausteine.net
* Generated by: https://github.com/openapitools/openapi-generator.git
*/
namespace BreCalClient.misc.Model
{
/// <summary>
/// fields that a user may change
/// </summary>
[DataContract(Name = "user_details")]
public partial class UserDetails : IEquatable<UserDetails>, IValidatableObject
{
/// <summary>
/// Initializes a new instance of the <see cref="UserDetails" /> class.
/// </summary>
/// <param name="id">id.</param>
/// <param name="oldPassword">oldPassword.</param>
/// <param name="newPassword">newPassword.</param>
/// <param name="firstName">firstName.</param>
/// <param name="lastName">lastName.</param>
/// <param name="userPhone">userPhone.</param>
public UserDetails(int id = default(int), string oldPassword = default(string), string newPassword = default(string), string firstName = default(string), string lastName = default(string), string userPhone = default(string))
{
this.Id = id;
this.OldPassword = oldPassword;
this.NewPassword = newPassword;
this.FirstName = firstName;
this.LastName = lastName;
this.UserPhone = userPhone;
}
/// <summary>
/// Gets or Sets Id
/// </summary>
[DataMember(Name = "id", EmitDefaultValue = true)]
public int Id { get; set; }
/// <summary>
/// Gets or Sets OldPassword
/// </summary>
[DataMember(Name = "old_password", EmitDefaultValue = true)]
public string OldPassword { get; set; }
/// <summary>
/// Gets or Sets NewPassword
/// </summary>
[DataMember(Name = "new_password", EmitDefaultValue = true)]
public string NewPassword { get; set; }
/// <summary>
/// Gets or Sets FirstName
/// </summary>
[DataMember(Name = "first_name", EmitDefaultValue = true)]
public string FirstName { get; set; }
/// <summary>
/// Gets or Sets LastName
/// </summary>
[DataMember(Name = "last_name", EmitDefaultValue = true)]
public string LastName { get; set; }
/// <summary>
/// Gets or Sets UserPhone
/// </summary>
[DataMember(Name = "user_phone", EmitDefaultValue = true)]
public string UserPhone { get; set; }
/// <summary>
/// Returns the string presentation of the object
/// </summary>
/// <returns>String presentation of the object</returns>
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("class UserDetails {\n");
sb.Append(" Id: ").Append(Id).Append("\n");
sb.Append(" OldPassword: ").Append(OldPassword).Append("\n");
sb.Append(" NewPassword: ").Append(NewPassword).Append("\n");
sb.Append(" FirstName: ").Append(FirstName).Append("\n");
sb.Append(" LastName: ").Append(LastName).Append("\n");
sb.Append(" UserPhone: ").Append(UserPhone).Append("\n");
sb.Append("}\n");
return sb.ToString();
}
/// <summary>
/// Returns the JSON string presentation of the object
/// </summary>
/// <returns>JSON string presentation of the object</returns>
public virtual string ToJson()
{
return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
}
/// <summary>
/// Returns true if objects are equal
/// </summary>
/// <param name="input">Object to be compared</param>
/// <returns>Boolean</returns>
public override bool Equals(object input)
{
return this.Equals(input as UserDetails);
}
/// <summary>
/// Returns true if UserDetails instances are equal
/// </summary>
/// <param name="input">Instance of UserDetails to be compared</param>
/// <returns>Boolean</returns>
public bool Equals(UserDetails input)
{
if (input == null)
{
return false;
}
return
(
this.Id == input.Id ||
this.Id.Equals(input.Id)
) &&
(
this.OldPassword == input.OldPassword ||
(this.OldPassword != null &&
this.OldPassword.Equals(input.OldPassword))
) &&
(
this.NewPassword == input.NewPassword ||
(this.NewPassword != null &&
this.NewPassword.Equals(input.NewPassword))
) &&
(
this.FirstName == input.FirstName ||
(this.FirstName != null &&
this.FirstName.Equals(input.FirstName))
) &&
(
this.LastName == input.LastName ||
(this.LastName != null &&
this.LastName.Equals(input.LastName))
) &&
(
this.UserPhone == input.UserPhone ||
(this.UserPhone != null &&
this.UserPhone.Equals(input.UserPhone))
);
}
/// <summary>
/// Gets the hash code
/// </summary>
/// <returns>Hash code</returns>
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hashCode = 41;
hashCode = (hashCode * 59) + this.Id.GetHashCode();
if (this.OldPassword != null)
{
hashCode = (hashCode * 59) + this.OldPassword.GetHashCode();
}
if (this.NewPassword != null)
{
hashCode = (hashCode * 59) + this.NewPassword.GetHashCode();
}
if (this.FirstName != null)
{
hashCode = (hashCode * 59) + this.FirstName.GetHashCode();
}
if (this.LastName != null)
{
hashCode = (hashCode * 59) + this.LastName.GetHashCode();
}
if (this.UserPhone != null)
{
hashCode = (hashCode * 59) + this.UserPhone.GetHashCode();
}
return hashCode;
}
}
/// <summary>
/// To validate all properties of the instance
/// </summary>
/// <param name="validationContext">Validation context</param>
/// <returns>Validation Result</returns>
IEnumerable<System.ComponentModel.DataAnnotations.ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
{
yield break;
}
}
}

View File

@ -1,7 +1,7 @@
openapi: '3.0.0' openapi: "3.0.0"
info: info:
version: '0.3.0' version: "0.3.0"
title: 'Bremen calling API' title: "Bremen calling API"
description: Administer DEBRE ship calls, times and notifications description: Administer DEBRE ship calls, times and notifications
termsOfService: "https://www.bsmd.de/" # url to terms page termsOfService: "https://www.bsmd.de/" # url to terms page
contact: contact:
@ -14,7 +14,7 @@ info:
servers: servers:
# tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html # tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html
- url : "https://brecal.bsmd-emswe.eu/" - url: "https://brecal.bsmd-emswe.eu/"
description: "Test server hosted on vcup" description: "Test server hosted on vcup"
paths: paths:
@ -28,22 +28,42 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/credentials' $ref: "#/components/schemas/credentials"
responses: responses:
200: 200:
description: Successful response description: Successful response
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/login_result' $ref: "#/components/schemas/login_result"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
403: 403:
$ref: '#/components/responses/403' $ref: "#/components/responses/403"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/user:
put:
summary: Update user details (first/last name, phone, password)
requestBody:
description: User details
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/user_details"
responses:
400:
$ref: "#/components/responses/400"
401:
$ref: "#/components/responses/401"
500:
$ref: "#/components/responses/500"
503:
$ref: "#/components/responses/503"
/shipcalls: /shipcalls:
get: get:
@ -61,15 +81,15 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/shipcalls' $ref: "#/components/schemas/shipcalls"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
post: post:
summary: Create a new ship call summary: Create a new ship call
requestBody: requestBody:
@ -78,16 +98,16 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/shipcall' $ref: "#/components/schemas/shipcall"
responses: responses:
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
put: put:
summary: Updates a ship call summary: Updates a ship call
@ -97,16 +117,16 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/shipcall' $ref: "#/components/schemas/shipcall"
responses: responses:
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/ships: /ships:
get: get:
@ -117,15 +137,15 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/ship_list' $ref: "#/components/schemas/ship_list"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/participants: /participants:
get: get:
@ -143,17 +163,17 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/participant_list' $ref: "#/components/schemas/participant_list"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
404: 404:
$ref: '#/components/responses/404' $ref: "#/components/responses/404"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/times: /times:
get: get:
@ -170,15 +190,15 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/times_list' $ref: "#/components/schemas/times_list"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
post: post:
summary: Create a new times entry for a ship call summary: Create a new times entry for a ship call
@ -188,16 +208,16 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/times' $ref: "#/components/schemas/times"
responses: responses:
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
put: put:
summary: Update a times entry for a ship call summary: Update a times entry for a ship call
@ -207,16 +227,16 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/times' $ref: "#/components/schemas/times"
responses: responses:
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
delete: delete:
summary: Delete a times entry for a ship call. summary: Delete a times entry for a ship call.
@ -225,16 +245,16 @@ paths:
in: query in: query
required: true required: true
schema: schema:
$ref: '#/components/schemas/timesId' $ref: "#/components/schemas/timesId"
responses: responses:
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/notifications: /notifications:
get: get:
@ -251,22 +271,22 @@ paths:
required: true required: true
description: "**Id of ship call**. *Example: 52*. Id given in ship call list" description: "**Id of ship call**. *Example: 52*. Id given in ship call list"
schema: schema:
$ref: '#/components/schemas/shipcallId' $ref: "#/components/schemas/shipcallId"
responses: responses:
200: 200:
description: notification list description: notification list
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/notification' $ref: "#/components/schemas/notification"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
/berths: /berths:
get: get:
summary: Gets a list of all berths registered summary: Gets a list of all berths registered
@ -276,15 +296,15 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/berth_list' $ref: "#/components/schemas/berth_list"
400: 400:
$ref: '#/components/responses/400' $ref: "#/components/responses/400"
401: 401:
$ref: '#/components/responses/401' $ref: "#/components/responses/401"
500: 500:
$ref: '#/components/responses/500' $ref: "#/components/responses/500"
503: 503:
$ref: '#/components/responses/503' $ref: "#/components/responses/503"
components: components:
schemas: schemas:
credentials: credentials:
@ -294,9 +314,9 @@ components:
- password - password
properties: properties:
username: username:
type : string type: string
password: password:
type : string type: string
format: password format: password
timesId: timesId:
description: The unique identifier for a times entry description: The unique identifier for a times entry
@ -313,7 +333,7 @@ components:
- eta - eta
properties: properties:
id: id:
$ref: '#/components/schemas/shipcallId' $ref: "#/components/schemas/shipcallId"
ship_id: ship_id:
type: integer type: integer
type: type:
@ -403,7 +423,7 @@ components:
shipcalls: shipcalls:
type: array type: array
items: items:
$ref: '#/components/schemas/shipcall' $ref: "#/components/schemas/shipcall"
times: times:
type: object type: object
@ -469,7 +489,7 @@ components:
times_list: times_list:
type: array type: array
items: items:
$ref: '#/components/schemas/times' $ref: "#/components/schemas/times"
berth: berth:
type: object type: object
@ -500,7 +520,7 @@ components:
berth_list: berth_list:
type: array type: array
items: items:
$ref: '#/components/schemas/berth' $ref: "#/components/schemas/berth"
ship: ship:
type: object type: object
@ -552,7 +572,7 @@ components:
ship_list: ship_list:
type: array type: array
items: items:
$ref: '#/components/schemas/ship' $ref: "#/components/schemas/ship"
notification: notification:
type: object type: object
@ -583,7 +603,7 @@ components:
notification_list: notification_list:
type: array type: array
items: items:
$ref: '#/components/schemas/notification' $ref: "#/components/schemas/notification"
participant: participant:
type: object type: object
@ -619,7 +639,7 @@ components:
participant_list: participant_list:
type: array type: array
items: items:
$ref: '#/components/schemas/participant' $ref: "#/components/schemas/participant"
login_result: login_result:
type: object type: object
@ -643,6 +663,28 @@ components:
token: token:
type: string type: string
user_details:
type: object
description: fields that a user may change
properties:
id:
type: integer
old_password:
type: string
nullable: true
new_password:
type: string
nullable: true
first_name:
type: string
nullable: true
last_name:
type: string
nullable: true
user_phone:
type: string
nullable: true
Error: Error:
type: object type: object
required: required:
@ -663,25 +705,25 @@ components:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/Error' $ref: "#/components/schemas/Error"
401: 401:
description: Not authorized description: Not authorized
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/Error' $ref: "#/components/schemas/Error"
500: 500:
description: Unexpected error description: Unexpected error
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/Error' $ref: "#/components/schemas/Error"
503: 503:
description: Not available description: Not available
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/Error' $ref: "#/components/schemas/Error"
security: security:
- ApiKey: [] - ApiKey: []

View File

@ -7,7 +7,7 @@
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:p = "clr-namespace:BreCalClient.Resources" xmlns:p = "clr-namespace:BreCalClient.Resources"
mc:Ignorable="d" mc:Ignorable="d"
Title="Help" Height="250" Width="500"> Title="Help" Height="270" Width="500">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="180" /> <ColumnDefinition Width="180" />

View File

@ -1,17 +1,11 @@
using System; // Copyright (c) 2023 schick Informatik
using System.Collections.Generic; // Description: Show about info and allow user detail editing
//
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace BreCalClient namespace BreCalClient
{ {
@ -45,7 +39,7 @@ namespace BreCalClient
private void buttonChangePassword_Click(object sender, RoutedEventArgs e) private void buttonChangePassword_Click(object sender, RoutedEventArgs e)
{ {
this.ChangePasswordRequested?.Invoke(this.wpBoxOldPassword.Text, this.wpBoxNewPassword.Text); this.ChangePasswordRequested?.Invoke(this.wpBoxOldPassword.Password, this.wpBoxNewPassword.Password);
} }
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e) private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
@ -57,10 +51,11 @@ namespace BreCalClient
private void wpBoxOldPassword_TextChanged(object sender, TextChangedEventArgs e) private void wpBoxOldPassword_TextChanged(object sender, TextChangedEventArgs e)
{ {
this.buttonChangePassword.IsEnabled = this.buttonChangePassword.IsEnabled =
(this.wpBoxOldPassword.Text.Length > 0) && (this.wpBoxOldPassword.Password.Length > 0) &&
(this.wpBoxNewPassword.Text.Length > 0) && (this.wpBoxNewPassword.Password.Length > 0) &&
(this.wpBoxNewPasswordRepeat.Text.Length > 0) && (this.wpBoxNewPasswordRepeat.Password.Length > 0) &&
(this.wpBoxNewPassword.Text.Equals(this.wpBoxNewPasswordRepeat.Text)); this.wpBoxNewPassword.Password.Equals(this.wpBoxNewPasswordRepeat.Password) &&
(!this.wpBoxNewPassword.Password.Equals(this.wpBoxOldPassword.Password));
} }
#endregion #endregion

View File

@ -134,12 +134,35 @@ namespace BreCalClient
} }
} }
private void buttonInfo_Click(object sender, RoutedEventArgs e) private void buttonInfo_Click(object sender, RoutedEventArgs e)
{ {
AboutDialog ad = new(); AboutDialog ad = new();
ad.ChangePasswordRequested += (oldPw, newPw) => ad.ChangePasswordRequested += async (oldPw, newPw) =>
{ {
if (_loginResult != null)
{
UserDetails ud = new()
{
Id = _loginResult.Id,
FirstName = _loginResult.FirstName,
LastName = _loginResult.LastName,
UserPhone = _loginResult.UserPhone,
OldPassword = oldPw,
NewPassword = newPw
};
try
{
await _api.UserPutAsync(ud);
}
catch (Exception ex)
{
this.Dispatcher.Invoke(new Action(() =>
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}));
}
}
}; };
ad.ShowDialog(); ad.ShowDialog();
} }

View File

@ -11,6 +11,7 @@ from .api import notifications
from .api import berths from .api import berths
from .api import ships from .api import ships
from .api import login from .api import login
from .api import user
sessions = dict() sessions = dict()
@ -39,6 +40,7 @@ def create_app(test_config=None):
app.register_blueprint(berths.bp) app.register_blueprint(berths.bp)
app.register_blueprint(ships.bp) app.register_blueprint(ships.bp)
app.register_blueprint(login.bp) app.register_blueprint(login.bp)
app.register_blueprint(user.bp)
logging.basicConfig(filename='brecal.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s') logging.basicConfig(filename='brecal.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')

View File

@ -0,0 +1,24 @@
from flask import Blueprint, request
from ..schemas import model
from .. import impl
from ..services.auth_guard import auth_guard
import json
import logging
bp = Blueprint('user', __name__)
@bp.route('/user', methods=['put'])
@auth_guard() # no restriction by role
def PutUser():
try:
content = request.get_json(force=True)
loadedModel = model.UserSchema().load(data=content, many=False, partial=True)
except Exception as ex:
logging.error(ex)
print(ex)
return json.dumps("bad format"), 400
return impl.user.PutUser(loadedModel)

View File

@ -5,3 +5,4 @@ from . import shipcalls
from . import times from . import times
from . import ships from . import ships
from . import login from . import login
from . import user

View File

@ -14,7 +14,7 @@ def GetUser(options):
hash = bcrypt.hashpw(options["password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8') hash = bcrypt.hashpw(options["password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8')
pooledConnection = local_db.getPoolConnection() pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection) commands = pydapper.using(pooledConnection)
data = commands.query("SELECT id, participant_id, first_name, last_name, user_name, user_email, user_phone, password_hash, api_key FROM user WHERE user_name = ?username? OR user_email = ?username?", data = commands.query("SELECT id, participant_id, first_name, last_name, user_name, user_email, user_phone, password_hash, api_key, created, modified FROM user WHERE user_name = ?username? OR user_email = ?username?",
model=model.User, param={"username" : options["username"]}) model=model.User, param={"username" : options["username"]})
pooledConnection.close() pooledConnection.close()
# print(data) # print(data)

View File

@ -0,0 +1,71 @@
import json
import logging
import pydapper
import bcrypt
from ..schemas import model
from .. import local_db
def PutUser(schemaModel):
"""
:param schemaModel: The deserialized dict of the request
"""
# This updates an *existing* entry
try:
pooledConnection = local_db.getPoolConnection()
commands = pydapper.using(pooledConnection)
# test if object to update is found
sentinel = object()
theuser = commands.query_single_or_default("SELECT * FROM user where id = ?id?", sentinel, param={"id" : schemaModel["id"]}, model=model.User)
if theuser is sentinel:
pooledConnection.close()
return json.dumps("no such record"), 404, {'Content-Type': 'application/json; charset=utf-8'}
# see if we need to update public fields
if "first_name" in schemaModel or "last_name" in schemaModel or "user_phone" in schemaModel:
query = "UPDATE user SET "
isNotFirst = False
for key in schemaModel.keys():
if key == "id":
continue
if key == "old_password":
continue
if key == "new_password":
continue
if isNotFirst:
query += ", "
isNotFirst = True
query += key + " = ?" + key + "? "
query += "WHERE id = ?id?"
affected_rows = commands.execute(query, param=schemaModel)
# update password if available and old pw is (correctly!) given
if "old_password" in schemaModel and schemaModel["old_password"] and "new_password" in schemaModel and schemaModel["new_password"]:
if bcrypt.checkpw(schemaModel["old_password"].encode("utf-8"), bytes(theuser.password_hash, "utf-8")): # old pw matches
password_hash = bcrypt.hashpw(schemaModel["new_password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8')
query = "UPDATE user SET password_hash = ?password_hash? WHERE id = ?id?"
commands.execute(query, param={"password_hash" : password_hash, "id" : schemaModel["id"]})
else:
result = {}
result["message"] = "old password invalid"
return json.dumps(result), 400, {'Content-Type': 'application/json; charset=utf-8'}
pooledConnection.close()
return json.dumps({"id" : schemaModel["id"]}), 200
except Exception as ex:
logging.error(ex)
print(ex)
result = {}
result["message"] = "call failed"
return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}

View File

@ -146,6 +146,19 @@ class TimesSchema(Schema):
created = fields.DateTime(Required = False) created = fields.DateTime(Required = False)
modified = fields.DateTime(Required = False) modified = fields.DateTime(Required = False)
# deserialize PUT object target
class UserSchema(Schema):
def __init__(self):
super().__init__(unknown=None)
pass
id = fields.Int(required=True)
first_name = fields.Str(required=False)
last_name = fields.Str(required=False)
user_phone = fields.Str(required=False)
old_password = fields.Str(required=False)
new_password = fields.Str(required=False)
@dataclass @dataclass
class Times: class Times:
@ -178,6 +191,8 @@ class User:
user_phone: str user_phone: str
password_hash: str password_hash: str
api_key: str api_key: str
created: datetime
modified: datetime
@dataclass @dataclass
class Ship(Schema): class Ship(Schema):