diff --git a/misc/BreCalApi.cs b/misc/BreCalApi.cs index c16d7a9..3a006be 100644 --- a/misc/BreCalApi.cs +++ b/misc/BreCalApi.cs @@ -1,7 +1,7 @@ //---------------------- // -// 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 // //---------------------- @@ -280,6 +280,25 @@ namespace BreCalClient.misc.Api /// Index associated with the operation. /// ApiResponse of Object(void) ApiResponse TimesPutWithHttpInfo(Times times, int operationIndex = 0); + /// + /// Update user details (first/last name, phone, password) + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// + void UserPut(UserDetails userDetails, int operationIndex = 0); + /// + /// Update user details (first/last name, phone, password) + /// + /// + /// + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// ApiResponse of Object(void) + ApiResponse UserPutWithHttpInfo(UserDetails userDetails, int operationIndex = 0); #endregion Synchronous Operations } /// @@ -572,6 +591,30 @@ namespace BreCalClient.misc.Api /// Cancellation Token to cancel the request. /// Task of ApiResponse System.Threading.Tasks.Task> TimesPutWithHttpInfoAsync(Times times, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Update user details (first/last name, phone, password) + /// + /// + /// + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// Cancellation Token to cancel the request. + /// Task of void + System.Threading.Tasks.Task UserPutAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Update user details (first/last name, phone, password) + /// + /// + /// + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// Cancellation Token to cancel the request. + /// Task of ApiResponse + System.Threading.Tasks.Task> UserPutWithHttpInfoAsync(UserDetails userDetails, int operationIndex = 0, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); #endregion Asynchronous Operations } /// @@ -2143,6 +2186,134 @@ namespace BreCalClient.misc.Api } return localVarResponse; } + /// + /// Update user details (first/last name, phone, password) + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// + public void UserPut(UserDetails userDetails, int operationIndex = 0) + { + UserPutWithHttpInfo(userDetails); + } + /// + /// Update user details (first/last name, phone, password) + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// ApiResponse of Object(void) + public BreCalClient.misc.Client.ApiResponse 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("/user", localVarRequestOptions, this.Configuration); + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UserPut", localVarResponse); + if (_exception != null) + { + throw _exception; + } + } + return localVarResponse; + } + /// + /// Update user details (first/last name, phone, password) + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// Cancellation Token to cancel the request. + /// Task of void + 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); + } + /// + /// Update user details (first/last name, phone, password) + /// + /// Thrown when fails to make API call + /// User details + /// Index associated with the operation. + /// Cancellation Token to cancel the request. + /// Task of ApiResponse + public async System.Threading.Tasks.Task> 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("/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 +{ + /// + /// fields that a user may change + /// + [DataContract(Name = "user_details")] + public partial class UserDetails : IEquatable, IValidatableObject + { + /// + /// Initializes a new instance of the class. + /// + /// id. + /// oldPassword. + /// newPassword. + /// firstName. + /// lastName. + /// userPhone. + 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; + } + /// + /// Gets or Sets Id + /// + [DataMember(Name = "id", EmitDefaultValue = true)] + public int Id { get; set; } + /// + /// Gets or Sets OldPassword + /// + [DataMember(Name = "old_password", EmitDefaultValue = true)] + public string OldPassword { get; set; } + /// + /// Gets or Sets NewPassword + /// + [DataMember(Name = "new_password", EmitDefaultValue = true)] + public string NewPassword { get; set; } + /// + /// Gets or Sets FirstName + /// + [DataMember(Name = "first_name", EmitDefaultValue = true)] + public string FirstName { get; set; } + /// + /// Gets or Sets LastName + /// + [DataMember(Name = "last_name", EmitDefaultValue = true)] + public string LastName { get; set; } + /// + /// Gets or Sets UserPhone + /// + [DataMember(Name = "user_phone", EmitDefaultValue = true)] + public string UserPhone { get; set; } + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + 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(); + } + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as UserDetails); + } + /// + /// Returns true if UserDetails instances are equal + /// + /// Instance of UserDetails to be compared + /// Boolean + 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)) + ); + } + /// + /// Gets the hash code + /// + /// Hash code + 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; + } + } + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } +} + diff --git a/misc/BreCalApi.yaml b/misc/BreCalApi.yaml index cc73737..0fa15ff 100644 --- a/misc/BreCalApi.yaml +++ b/misc/BreCalApi.yaml @@ -1,690 +1,732 @@ -openapi: '3.0.0' +openapi: "3.0.0" info: - version: '0.3.0' - title: 'Bremen calling API' - description: Administer DEBRE ship calls, times and notifications - termsOfService: "https://www.bsmd.de/" # url to terms page - contact: - name: "Bremen calling API" - url: "https://www.textbausteine.net" - email: "info@textbausteine.net" - license: - name: "Use at your own risk" - url: "https://www.bsmd.de/license" + version: "0.3.0" + title: "Bremen calling API" + description: Administer DEBRE ship calls, times and notifications + termsOfService: "https://www.bsmd.de/" # url to terms page + contact: + name: "Bremen calling API" + url: "https://www.textbausteine.net" + email: "info@textbausteine.net" + license: + name: "Use at your own risk" + url: "https://www.bsmd.de/license" servers: - # tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html - - url : "https://brecal.bsmd-emswe.eu/" - description: "Test server hosted on vcup" + # tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html + - url: "https://brecal.bsmd-emswe.eu/" + description: "Test server hosted on vcup" paths: - # tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step4_paths_object.html - /login: - post: - summary: Returns a JWT session token and user data if successful - requestBody: - description: Login credentials - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/credentials' - responses: - 200: - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/login_result' - 400: - $ref: '#/components/responses/400' - 403: - $ref: '#/components/responses/403' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + # tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step4_paths_object.html + /login: + post: + summary: Returns a JWT session token and user data if successful + requestBody: + description: Login credentials + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/credentials" + responses: + 200: + description: Successful response + content: + application/json: + schema: + $ref: "#/components/schemas/login_result" + 400: + $ref: "#/components/responses/400" + 403: + $ref: "#/components/responses/403" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - /shipcalls: - get: - summary: Gets a list of ship calls - #parameters: - # - name: participant_id - # in: query - # required: true - # description: "**Id of participant**. *Example: 2*. Id of participant entity requesting ship calls" - # schema: - # type: integer - responses: - 200: - description: ship call list - content: - application/json: - schema: - $ref: '#/components/schemas/shipcalls' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' - post: - summary: Create a new ship call - requestBody: - description: Creates a new ship call. **Do not** provide id parameter. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/shipcall' - responses: - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 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" - put: - summary: Updates a ship call - requestBody: - description: Creates a new ship call. The id parameter is **required**. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/shipcall' - responses: - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + /shipcalls: + get: + summary: Gets a list of ship calls + #parameters: + # - name: participant_id + # in: query + # required: true + # description: "**Id of participant**. *Example: 2*. Id of participant entity requesting ship calls" + # schema: + # type: integer + responses: + 200: + description: ship call list + content: + application/json: + schema: + $ref: "#/components/schemas/shipcalls" + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" + post: + summary: Create a new ship call + requestBody: + description: Creates a new ship call. **Do not** provide id parameter. + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/shipcall" + responses: + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - /ships: - get: - summary: gets a list of registered shipcalls - responses: - 200: - description: list of ships - content: - application/json: - schema: - $ref: '#/components/schemas/ship_list' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + put: + summary: Updates a ship call + requestBody: + description: Creates a new ship call. The id parameter is **required**. + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/shipcall" + responses: + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - /participants: - get: - summary: gets a particular participant entry corresponding to user id - parameters: - - name: user_id - in: query - required: false - description: "**Id of user**. *Example: 2*. User id returned by verify call." - schema: - type: integer - responses: - 200: - description: ship call list - content: - application/json: - schema: - $ref: '#/components/schemas/participant_list' - 400: - $ref: '#/components/responses/400' - 404: - $ref: '#/components/responses/404' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + /ships: + get: + summary: gets a list of registered shipcalls + responses: + 200: + description: list of ships + content: + application/json: + schema: + $ref: "#/components/schemas/ship_list" + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - /times: - get: - summary: Get all recorded times for a a ship call - parameters: - - name: shipcall_id - in: query - description: "**Id**. *Example: 42*. Id of referenced ship call." - schema: - type: integer - responses: - 200: - description: list of recorded times - content: - application/json: - schema: - $ref: '#/components/schemas/times_list' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + /participants: + get: + summary: gets a particular participant entry corresponding to user id + parameters: + - name: user_id + in: query + required: false + description: "**Id of user**. *Example: 2*. User id returned by verify call." + schema: + type: integer + responses: + 200: + description: ship call list + content: + application/json: + schema: + $ref: "#/components/schemas/participant_list" + 400: + $ref: "#/components/responses/400" + 404: + $ref: "#/components/responses/404" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - post: - summary: Create a new times entry for a ship call - requestBody: - description: Times entry that will be added to the ship call. **Do not** provide id parameter. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/times' - responses: - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + /times: + get: + summary: Get all recorded times for a a ship call + parameters: + - name: shipcall_id + in: query + description: "**Id**. *Example: 42*. Id of referenced ship call." + schema: + type: integer + responses: + 200: + description: list of recorded times + content: + application/json: + schema: + $ref: "#/components/schemas/times_list" + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - put: - summary: Update a times entry for a ship call - requestBody: - description: Times entry that will be added to the ship call. The id parameter is **required**. - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/times' - responses: - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + post: + summary: Create a new times entry for a ship call + requestBody: + description: Times entry that will be added to the ship call. **Do not** provide id parameter. + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/times" + responses: + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - delete: - summary: Delete a times entry for a ship call. - parameters: - - name: id - in: query - required: true - schema: - $ref: '#/components/schemas/timesId' - responses: - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + put: + summary: Update a times entry for a ship call + requestBody: + description: Times entry that will be added to the ship call. The id parameter is **required**. + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/times" + responses: + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" - /notifications: - get: - summary: Gets a list of notifications pursuant to a specified participant and ship call - parameters: - - name: participant_id - in: query - required: true - description: "**Id of participant**. *Example: 2*. Id returned through loading of participant" - schema: - type: integer - - name: shipcall_id - in: query - required: true - description: "**Id of ship call**. *Example: 52*. Id given in ship call list" - schema: - $ref: '#/components/schemas/shipcallId' - responses: - 200: - description: notification list - content: - application/json: - schema: - $ref: '#/components/schemas/notification' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' - /berths: - get: - summary: Gets a list of all berths registered - responses: - 200: - description: list of berths - content: - application/json: - schema: - $ref: '#/components/schemas/berth_list' - 400: - $ref: '#/components/responses/400' - 401: - $ref: '#/components/responses/401' - 500: - $ref: '#/components/responses/500' - 503: - $ref: '#/components/responses/503' + delete: + summary: Delete a times entry for a ship call. + parameters: + - name: id + in: query + required: true + schema: + $ref: "#/components/schemas/timesId" + responses: + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" + + /notifications: + get: + summary: Gets a list of notifications pursuant to a specified participant and ship call + parameters: + - name: participant_id + in: query + required: true + description: "**Id of participant**. *Example: 2*. Id returned through loading of participant" + schema: + type: integer + - name: shipcall_id + in: query + required: true + description: "**Id of ship call**. *Example: 52*. Id given in ship call list" + schema: + $ref: "#/components/schemas/shipcallId" + responses: + 200: + description: notification list + content: + application/json: + schema: + $ref: "#/components/schemas/notification" + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" + /berths: + get: + summary: Gets a list of all berths registered + responses: + 200: + description: list of berths + content: + application/json: + schema: + $ref: "#/components/schemas/berth_list" + 400: + $ref: "#/components/responses/400" + 401: + $ref: "#/components/responses/401" + 500: + $ref: "#/components/responses/500" + 503: + $ref: "#/components/responses/503" components: - schemas: - credentials: - type: object - required: - - username - - password - properties: - username: - type : string - password: - type : string - format: password - timesId: - description: The unique identifier for a times entry - type: integer - shipcallId: - description: The unique identifier of a ship call - type: integer - shipcall: - type: object - required: - - id - - ship_id - - type - - eta - properties: - id: - $ref: '#/components/schemas/shipcallId' - ship_id: - type: integer - type: - type: string - enum: - - incoming - - outgoing - - shifting - eta: - type: string - format: date-time - voyage: - type: string - maxLength: 16 - nullable: true - etd: - type: string - format: date-time - nullable: true - arrival_berth_id: - type: integer - nullable: true - departure_berth_id: - type: integer - nullable: true - tug_reguired: - type: boolean - nullable: true - pilot_required: - type: boolean - nullable: true - flags: - type: integer - nullable: true - pier_side: - type: boolean - nullable: true - bunkering: - type: boolean - nullable: true - replenishing_terminal: - type: boolean - nullable: true - replenishing_lock: - type: boolean - nullable: true - draft: - type: number - format: float - nullable: true - tidal_window_from: - type: string - format: date-time - nullable: true - tidal_window_to: - type: string - format: date-time - nullable: true - rain_sensitive_cargo: - type: boolean - nullable: true - recommended_tugs: - type: integer - nullable: true - anchored: - type: boolean - nullable: true - moored_lock: - type: boolean - nullable: true - canceled: - type: boolean - nullable: true - participants: - type: array - items: + schemas: + credentials: + type: object + required: + - username + - password + properties: + username: + type: string + password: + type: string + format: password + timesId: + description: The unique identifier for a times entry type: integer - example: [1, 5, 7] - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true + shipcallId: + description: The unique identifier of a ship call + type: integer + shipcall: + type: object + required: + - id + - ship_id + - type + - eta + properties: + id: + $ref: "#/components/schemas/shipcallId" + ship_id: + type: integer + type: + type: string + enum: + - incoming + - outgoing + - shifting + eta: + type: string + format: date-time + voyage: + type: string + maxLength: 16 + nullable: true + etd: + type: string + format: date-time + nullable: true + arrival_berth_id: + type: integer + nullable: true + departure_berth_id: + type: integer + nullable: true + tug_reguired: + type: boolean + nullable: true + pilot_required: + type: boolean + nullable: true + flags: + type: integer + nullable: true + pier_side: + type: boolean + nullable: true + bunkering: + type: boolean + nullable: true + replenishing_terminal: + type: boolean + nullable: true + replenishing_lock: + type: boolean + nullable: true + draft: + type: number + format: float + nullable: true + tidal_window_from: + type: string + format: date-time + nullable: true + tidal_window_to: + type: string + format: date-time + nullable: true + rain_sensitive_cargo: + type: boolean + nullable: true + recommended_tugs: + type: integer + nullable: true + anchored: + type: boolean + nullable: true + moored_lock: + type: boolean + nullable: true + canceled: + type: boolean + nullable: true + participants: + type: array + items: + type: integer + example: [1, 5, 7] + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true - shipcalls: - type: array - items: - $ref: '#/components/schemas/shipcall' + shipcalls: + type: array + items: + $ref: "#/components/schemas/shipcall" - times: - type: object - description: the id parameter needs to be missing on POST and to be present on PUT (Update) calls, otherwise a 400 response will be generated - required: - - shipcall_id - - participant_id - properties: - id: - type: integer - eta_berth: - type: string - format: date-time - nullable: true - eta_berth_fixed: - type: boolean - nullable: true - etd_berth: - type: string - format: date-time - nullable: true - etd_berth_fixed: - type: boolean - nullable: true - lock_time: - type: string - format: date-time - nullable: true - lock_time_fixed: - type: boolean - nullable: true - zone_entry: - type: string - format: date-time - nullable: true - zone_entry_fixed: - type: boolean - nullable: true - operations_start: - type: string - format: date-time - nullable: true - operations_end: - type: string - format: date-time - nullable: true - remarks: - type: string - maxLength: 512 - nullable: true - shipcall_id: - type: integer - participant_id: - type: integer - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true + times: + type: object + description: the id parameter needs to be missing on POST and to be present on PUT (Update) calls, otherwise a 400 response will be generated + required: + - shipcall_id + - participant_id + properties: + id: + type: integer + eta_berth: + type: string + format: date-time + nullable: true + eta_berth_fixed: + type: boolean + nullable: true + etd_berth: + type: string + format: date-time + nullable: true + etd_berth_fixed: + type: boolean + nullable: true + lock_time: + type: string + format: date-time + nullable: true + lock_time_fixed: + type: boolean + nullable: true + zone_entry: + type: string + format: date-time + nullable: true + zone_entry_fixed: + type: boolean + nullable: true + operations_start: + type: string + format: date-time + nullable: true + operations_end: + type: string + format: date-time + nullable: true + remarks: + type: string + maxLength: 512 + nullable: true + shipcall_id: + type: integer + participant_id: + type: integer + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true - times_list: - type: array - items: - $ref: '#/components/schemas/times' + times_list: + type: array + items: + $ref: "#/components/schemas/times" - berth: - type: object - description: Ship berth used for a ship call - properties: - id: - type: integer - name: - type: string - maxLength: 128 - participant_id: - type: integer - nullable: true - lock: - type: boolean - nullable: true - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true - deleted: - type: boolean - default: false + berth: + type: object + description: Ship berth used for a ship call + properties: + id: + type: integer + name: + type: string + maxLength: 128 + participant_id: + type: integer + nullable: true + lock: + type: boolean + nullable: true + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true + deleted: + type: boolean + default: false - berth_list: - type: array - items: - $ref: '#/components/schemas/berth' + berth_list: + type: array + items: + $ref: "#/components/schemas/berth" - ship: - type: object - description: a ship - properties: - id: - type: integer - name: - type: string - maxLength: 64 - imo: - type: integer - nullable: true - callsign: - type: string - maxLength: 8 - nullable: true - participant_id: - type: integer - nullable: true - length: - type: number - format: float - nullable: true - width: - type: number - format: float - nullable: true - is_tug: - type: boolean - default: false - bollard_pull: - type: integer - nullable: true - eni: - type: integer - nullable: true - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true - deleted: - type: boolean - default: false + ship: + type: object + description: a ship + properties: + id: + type: integer + name: + type: string + maxLength: 64 + imo: + type: integer + nullable: true + callsign: + type: string + maxLength: 8 + nullable: true + participant_id: + type: integer + nullable: true + length: + type: number + format: float + nullable: true + width: + type: number + format: float + nullable: true + is_tug: + type: boolean + default: false + bollard_pull: + type: integer + nullable: true + eni: + type: integer + nullable: true + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true + deleted: + type: boolean + default: false - ship_list: - type: array - items: - $ref: '#/components/schemas/ship' + ship_list: + type: array + items: + $ref: "#/components/schemas/ship" - notification: - type: object - description: a notification created by the engine if a times entry violates a rule - properties: - id: - type: integer - times_id: - type: integer - participant_id: - type: integer - notification_type: - type: string - enum: [undefined, email, push] - timestamp: - type: string - format: date-time - acknowledged: - type: boolean - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true + notification: + type: object + description: a notification created by the engine if a times entry violates a rule + properties: + id: + type: integer + times_id: + type: integer + participant_id: + type: integer + notification_type: + type: string + enum: [undefined, email, push] + timestamp: + type: string + format: date-time + acknowledged: + type: boolean + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true - notification_list: - type: array - items: - $ref: '#/components/schemas/notification' + notification_list: + type: array + items: + $ref: "#/components/schemas/notification" - participant: - type: object - description: A organisational entity that participates in Bremen Calling - properties: - id: - type: integer - name: - type: string - maxLength: 128 - street: - type: string - maxLength: 128 - postal code: - type: string - maxLength: 5 - city: - type: string - maxLength: 64 - type: - type: integer - created: - type: string - format: date-time - modified: - type: string - format: date-time - nullable: true - deleted: - type: boolean - default: false + participant: + type: object + description: A organisational entity that participates in Bremen Calling + properties: + id: + type: integer + name: + type: string + maxLength: 128 + street: + type: string + maxLength: 128 + postal code: + type: string + maxLength: 5 + city: + type: string + maxLength: 64 + type: + type: integer + created: + type: string + format: date-time + modified: + type: string + format: date-time + nullable: true + deleted: + type: boolean + default: false - participant_list: - type: array - items: - $ref: '#/components/schemas/participant' + participant_list: + type: array + items: + $ref: "#/components/schemas/participant" - login_result: - type: object - description: result structure of a successful login attempt - properties: - id: - type: integer - participant_id: - type: integer - first_name: - type: string - last_name: - type: string - user_name: - type: string - user_phone: - type: string - exp: - type: number - format: float - token: - type: string + login_result: + type: object + description: result structure of a successful login attempt + properties: + id: + type: integer + participant_id: + type: integer + first_name: + type: string + last_name: + type: string + user_name: + type: string + user_phone: + type: string + exp: + type: number + format: float + token: + type: string - Error: - type: object - required: - - message - properties: - message: - description: A human readable error message - 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 - securitySchemes: - ApiKey: - type: apiKey - in: header - name: Authorization - responses: - 400: - description: Invalid input - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - 401: - description: Not authorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - 500: - description: Unexpected error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - 503: - description: Not available - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + Error: + type: object + required: + - message + properties: + message: + description: A human readable error message + type: string + + securitySchemes: + ApiKey: + type: apiKey + in: header + name: Authorization + responses: + 400: + description: Invalid input + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + 401: + description: Not authorized + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + 500: + description: Unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + 503: + description: Not available + content: + application/json: + schema: + $ref: "#/components/schemas/Error" security: - - ApiKey: [] + - ApiKey: [] externalDocs: - url: http://textbausteine.net/ - description: Extra documentation and conditions for Bremen Calling + url: http://textbausteine.net/ + description: Extra documentation and conditions for Bremen Calling diff --git a/src/BreCalClient/AboutDialog.xaml b/src/BreCalClient/AboutDialog.xaml index b055524..b45900a 100644 --- a/src/BreCalClient/AboutDialog.xaml +++ b/src/BreCalClient/AboutDialog.xaml @@ -7,7 +7,7 @@ xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:p = "clr-namespace:BreCalClient.Resources" mc:Ignorable="d" - Title="Help" Height="250" Width="500"> + Title="Help" Height="270" Width="500"> diff --git a/src/BreCalClient/AboutDialog.xaml.cs b/src/BreCalClient/AboutDialog.xaml.cs index e560e36..61e6154 100644 --- a/src/BreCalClient/AboutDialog.xaml.cs +++ b/src/BreCalClient/AboutDialog.xaml.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; +// Copyright (c) 2023 schick Informatik +// Description: Show about info and allow user detail editing +// + +using System; using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows; 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 { @@ -45,7 +39,7 @@ namespace BreCalClient 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) @@ -57,10 +51,11 @@ namespace BreCalClient private void wpBoxOldPassword_TextChanged(object sender, TextChangedEventArgs e) { this.buttonChangePassword.IsEnabled = - (this.wpBoxOldPassword.Text.Length > 0) && - (this.wpBoxNewPassword.Text.Length > 0) && - (this.wpBoxNewPasswordRepeat.Text.Length > 0) && - (this.wpBoxNewPassword.Text.Equals(this.wpBoxNewPasswordRepeat.Text)); + (this.wpBoxOldPassword.Password.Length > 0) && + (this.wpBoxNewPassword.Password.Length > 0) && + (this.wpBoxNewPasswordRepeat.Password.Length > 0) && + this.wpBoxNewPassword.Password.Equals(this.wpBoxNewPasswordRepeat.Password) && + (!this.wpBoxNewPassword.Password.Equals(this.wpBoxOldPassword.Password)); } #endregion diff --git a/src/BreCalClient/MainWindow.xaml.cs b/src/BreCalClient/MainWindow.xaml.cs index ca79547..38b5462 100644 --- a/src/BreCalClient/MainWindow.xaml.cs +++ b/src/BreCalClient/MainWindow.xaml.cs @@ -134,12 +134,35 @@ namespace BreCalClient } } + private void buttonInfo_Click(object sender, RoutedEventArgs e) { 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(); } diff --git a/src/server/BreCal/__init__.py b/src/server/BreCal/__init__.py index 5f67db0..e15818a 100644 --- a/src/server/BreCal/__init__.py +++ b/src/server/BreCal/__init__.py @@ -11,6 +11,7 @@ from .api import notifications from .api import berths from .api import ships from .api import login +from .api import user sessions = dict() @@ -39,6 +40,7 @@ def create_app(test_config=None): app.register_blueprint(berths.bp) app.register_blueprint(ships.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') diff --git a/src/server/BreCal/api/user.py b/src/server/BreCal/api/user.py new file mode 100644 index 0000000..bbd5b4b --- /dev/null +++ b/src/server/BreCal/api/user.py @@ -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) + diff --git a/src/server/BreCal/impl/__init__.py b/src/server/BreCal/impl/__init__.py index 4052c42..4e1e218 100644 --- a/src/server/BreCal/impl/__init__.py +++ b/src/server/BreCal/impl/__init__.py @@ -5,3 +5,4 @@ from . import shipcalls from . import times from . import ships from . import login +from . import user \ No newline at end of file diff --git a/src/server/BreCal/impl/login.py b/src/server/BreCal/impl/login.py index ed0aab8..cef9e4c 100644 --- a/src/server/BreCal/impl/login.py +++ b/src/server/BreCal/impl/login.py @@ -14,7 +14,7 @@ def GetUser(options): hash = bcrypt.hashpw(options["password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8') pooledConnection = local_db.getPoolConnection() 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"]}) pooledConnection.close() # print(data) diff --git a/src/server/BreCal/impl/user.py b/src/server/BreCal/impl/user.py new file mode 100644 index 0000000..ece0d5f --- /dev/null +++ b/src/server/BreCal/impl/user.py @@ -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'} + + + diff --git a/src/server/BreCal/schemas/model.py b/src/server/BreCal/schemas/model.py index e49ee77..439098b 100644 --- a/src/server/BreCal/schemas/model.py +++ b/src/server/BreCal/schemas/model.py @@ -146,6 +146,19 @@ class TimesSchema(Schema): created = 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 class Times: @@ -178,6 +191,8 @@ class User: user_phone: str password_hash: str api_key: str + created: datetime + modified: datetime @dataclass class Ship(Schema):