Compare commits
29 Commits
60baf02299
...
dc98b1d500
| Author | SHA1 | Date | |
|---|---|---|---|
| dc98b1d500 | |||
| a50cd9cc9a | |||
| d06669e943 | |||
| 6362f47d43 | |||
| c6954fb222 | |||
| 6d8b86280c | |||
| 2a1570d9f5 | |||
| d180dac600 | |||
| 8b4131332b | |||
| 27b9f46f30 | |||
| c8550431e0 | |||
| a1b807824e | |||
| 189626d61c | |||
| 3d76acb2f0 | |||
| 98c05aed3b | |||
| 98696aee93 | |||
| 7f706dfc51 | |||
| ab12e28d3d | |||
| e9a7e03ebf | |||
| f1c5bd3cd8 | |||
| bb13d74849 | |||
| 55cf17d169 | |||
| ea634a3af2 | |||
| 21471d4d41 | |||
| fce897fae4 | |||
| 64c6607076 | |||
| 6dedc04957 | |||
| 213f7cf58c | |||
| 49a8498bbe |
@ -5008,7 +5008,7 @@ namespace BreCalClient.misc.Client
|
||||
{
|
||||
Proxy = null;
|
||||
UserAgent = WebUtility.UrlEncode("OpenAPI-Generator/1.0.0/csharp");
|
||||
BasePath = "https://brecaldevel.bsmd-emswe.eu";
|
||||
BasePath = "https://brecaltest.bsmd-emswe.eu";
|
||||
DefaultHeaders = new ConcurrentDictionary<string, string>();
|
||||
ApiKey = new ConcurrentDictionary<string, string>();
|
||||
ApiKeyPrefix = new ConcurrentDictionary<string, string>();
|
||||
@ -5016,7 +5016,7 @@ namespace BreCalClient.misc.Client
|
||||
{
|
||||
{
|
||||
new Dictionary<string, object> {
|
||||
{"url", "https://brecaldevel.bsmd-emswe.eu"},
|
||||
{"url", "https://brecaltest.bsmd-emswe.eu"},
|
||||
{"description", "Development server hosted on vcup"},
|
||||
}
|
||||
}
|
||||
@ -5035,7 +5035,7 @@ namespace BreCalClient.misc.Client
|
||||
IDictionary<string, string> defaultHeaders,
|
||||
IDictionary<string, string> apiKey,
|
||||
IDictionary<string, string> apiKeyPrefix,
|
||||
string basePath = "https://brecaldevel.bsmd-emswe.eu") : this()
|
||||
string basePath = "https://brecaltest.bsmd-emswe.eu") : this()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(basePath))
|
||||
throw new ArgumentException("The provided basePath is invalid.", "basePath");
|
||||
|
||||
@ -14,7 +14,7 @@ info:
|
||||
name: Use at your own risk
|
||||
url: 'https://www.bsmd.de/license'
|
||||
servers:
|
||||
- url: 'https://brecaldevel.bsmd-emswe.eu'
|
||||
- url: 'https://brecaltest.bsmd-emswe.eu'
|
||||
description: Development server hosted on vcup
|
||||
tags:
|
||||
- name: user
|
||||
|
||||
@ -39,6 +39,25 @@ CREATE TABLE `berth` (
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=195 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Berth of ship for a ship call';
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
CREATE TABLE `history` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`participant_id` int unsigned NOT NULL,
|
||||
`user_id` int unsigned DEFAULT NULL,
|
||||
`shipcall_id` int unsigned NOT NULL,
|
||||
`timestamp` datetime NOT NULL COMMENT 'Time of saving',
|
||||
`eta` datetime DEFAULT NULL COMMENT 'Current ETA / ETD value (depends if shipcall or times were saved)',
|
||||
`type` int NOT NULL COMMENT 'shipcall or times',
|
||||
`operation` int NOT NULL COMMENT 'insert, update or delete',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `FK_HISTORY_PARTICIPANT_idx` (`participant_id`),
|
||||
KEY `FK_HISTORY_SHIPCALL_idx` (`shipcall_id`),
|
||||
KEY `FK_HISTORY_USER` (`user_id`),
|
||||
CONSTRAINT `FK_HISTORY_PARTICIPANT` FOREIGN KEY (`participant_id`) REFERENCES `participant` (`id`),
|
||||
CONSTRAINT `FK_HISTORY_SHIPCALL` FOREIGN KEY (`shipcall_id`) REFERENCES `shipcall` (`id`),
|
||||
CONSTRAINT `FK_HISTORY_USER` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=29292 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='This table stores a history of changes made to shipcalls so that everyone can see who changed what and when';
|
||||
|
||||
|
||||
--
|
||||
-- Table structure for table `notification`
|
||||
--
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
<applicationSettings>
|
||||
<BreCalClient.Properties.Settings>
|
||||
<setting name="BG_COLOR" serializeAs="String">
|
||||
<value>#1D751F</value>
|
||||
<value>#751D1F</value>
|
||||
</setting>
|
||||
<setting name="APP_TITLE" serializeAs="String">
|
||||
<value>!!Bremen calling Entwicklungsversion!!</value>
|
||||
@ -38,7 +38,7 @@
|
||||
<value>https://www.textbausteine.net/</value>
|
||||
</setting>
|
||||
<setting name="API_URL" serializeAs="String">
|
||||
<value>https://brecaldevel.bsmd-emswe.eu</value>
|
||||
<value>https://brecaltest.bsmd-emswe.eu</value>
|
||||
</setting>
|
||||
</BreCalClient.Properties.Settings>
|
||||
</applicationSettings>
|
||||
|
||||
@ -35,7 +35,7 @@ namespace BreCalClient
|
||||
this.ContentWrapper.Background = Brushes.Gray;
|
||||
break;
|
||||
case "MissingData":
|
||||
this.ContentWrapper.Background= Brushes.Yellow;
|
||||
this.ContentWrapper.Background = Brushes.DarkKhaki;
|
||||
break;
|
||||
case "Cancelled":
|
||||
this.ContentWrapper.Background = Brushes.DarkGray;
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<Title>Bremen calling client</Title>
|
||||
<Description>A Windows WPF client for the Bremen calling API.</Description>
|
||||
<ApplicationIcon>containership.ico</ApplicationIcon>
|
||||
<AssemblyName>BreCalDevelClient</AssemblyName>
|
||||
<AssemblyName>BreCalTestClient</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -4,8 +4,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.6.0.3</ApplicationVersion>
|
||||
<ApplicationRevision>5</ApplicationRevision>
|
||||
<ApplicationVersion>1.7.0.7</ApplicationVersion>
|
||||
<BootstrapperEnabled>True</BootstrapperEnabled>
|
||||
<Configuration>Debug</Configuration>
|
||||
<CreateDesktopShortcut>True</CreateDesktopShortcut>
|
||||
@ -27,10 +27,10 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<SelfContained>True</SelfContained>
|
||||
<SignatureAlgorithm>(none)</SignatureAlgorithm>
|
||||
<SignManifests>False</SignManifests>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows7.0</TargetFramework>
|
||||
<UpdateEnabled>True</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateRequired>False</UpdateRequired>
|
||||
<UpdateRequired>True</UpdateRequired>
|
||||
<WebPageFileName>Publish.html</WebPageFileName>
|
||||
<CreateDesktopShortcut>True</CreateDesktopShortcut>
|
||||
<ErrorReportUrl>https://www.bsmd-emswe.eu/</ErrorReportUrl>
|
||||
@ -38,8 +38,10 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<PublisherName>Informatikbüro Daniel Schick</PublisherName>
|
||||
<SuiteName>Bremen Calling</SuiteName>
|
||||
<SupportUrl>http://www.textbausteine.net/</SupportUrl>
|
||||
<PublishDir>bin\Debug\net6.0-windows\win-x64\app.publish\</PublishDir>
|
||||
<PublishDir>bin\Debug\net8.0-windows7.0\win-x64\app.publish\</PublishDir>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SkipPublishVerification>false</SkipPublishVerification>
|
||||
<MinimumRequiredVersion>1.7.0.7</MinimumRequiredVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PublishFile Include="containership.ico">
|
||||
|
||||
4
src/BreCalClient/Properties/Settings.Designer.cs
generated
4
src/BreCalClient/Properties/Settings.Designer.cs
generated
@ -25,7 +25,7 @@ namespace BreCalClient.Properties {
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#1D751F")]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("#751D1F")]
|
||||
public string BG_COLOR {
|
||||
get {
|
||||
return ((string)(this["BG_COLOR"]));
|
||||
@ -64,7 +64,7 @@ namespace BreCalClient.Properties {
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("https://brecaldevel.bsmd-emswe.eu")]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("https://brecaltest.bsmd-emswe.eu")]
|
||||
public string API_URL {
|
||||
get {
|
||||
return ((string)(this["API_URL"]));
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="BG_COLOR" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">#1D751F</Value>
|
||||
<Value Profile="(Default)">#751D1F</Value>
|
||||
</Setting>
|
||||
<Setting Name="APP_TITLE" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">!!Bremen calling Entwicklungsversion!!</Value>
|
||||
@ -15,7 +15,7 @@
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="API_URL" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">https://brecaldevel.bsmd-emswe.eu</Value>
|
||||
<Value Profile="(Default)">https://brecaltest.bsmd-emswe.eu</Value>
|
||||
</Setting>
|
||||
<Setting Name="Width" Type="System.Double" Scope="User">
|
||||
<Value Profile="(Default)">800</Value>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:p = "clr-namespace:BreCalClient.Resources"
|
||||
xmlns:sets="clr-namespace:BreCalClient.Properties"
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalDevelClient"
|
||||
xmlns:db="clr-namespace:BreCalClient;assembly=BreCalTestClient"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="135" d:DesignWidth="800">
|
||||
<Border BorderBrush="LightGray" Margin="1" BorderThickness="1">
|
||||
|
||||
@ -215,13 +215,13 @@ namespace BreCalClient
|
||||
switch (this.ShipcallControlModel?.Shipcall?.Type)
|
||||
{
|
||||
case ShipcallType.Arrival: // incoming
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_down_red.png"));
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/arrow_down_red.png"));
|
||||
break;
|
||||
case ShipcallType.Departure: // outgoing
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_up_blue.png"));
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/arrow_up_blue.png"));
|
||||
break;
|
||||
case ShipcallType.Shifting: // shifting
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/arrow_right_green.png"));
|
||||
this.imageShipcallType.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/arrow_right_green.png"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -230,13 +230,13 @@ namespace BreCalClient
|
||||
switch(this.ShipcallControlModel?.LightMode)
|
||||
{
|
||||
case EvaluationType.Green:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/check.png"));
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/check.png"));
|
||||
break;
|
||||
case EvaluationType.Yellow:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/sign_warning.png"));
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/sign_warning.png"));
|
||||
break;
|
||||
case EvaluationType.Red:
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalDevelClient;component/Resources/delete2.png"));
|
||||
this.imageEvaluation.Source = new BitmapImage(new Uri("pack://application:,,,/BreCalTestClient;component/Resources/delete2.png"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<applicationSettings>
|
||||
<RoleEditor.Properties.Settings>
|
||||
<setting name="ConnectionString" serializeAs="String">
|
||||
<value>Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_devel;Port=33306</value>
|
||||
<value>Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_test;Port=33307</value>
|
||||
</setting>
|
||||
</RoleEditor.Properties.Settings>
|
||||
</applicationSettings>
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
<Label Content="Street" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Postal code" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="City" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Active" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Deleted" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Type" Grid.Row="5" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Created" Grid.Row="6" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
<Label Content="Modified" Grid.Row="7" Grid.Column="1" HorizontalAlignment="Right"/>
|
||||
@ -67,7 +67,7 @@
|
||||
<TextBox x:Name="textBoxParticipantStreet" Grid.Row="1" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
|
||||
<TextBox x:Name="textBoxParticipantPostalCode" Grid.Row="2" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
|
||||
<TextBox x:Name="textBoxParticipantCity" Grid.Row="3" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
|
||||
<CheckBox x:Name="checkboxParticipantActive" Grid.Row="4" Grid.Column="2" VerticalAlignment="Center" />
|
||||
<CheckBox x:Name="checkboxParticipantDeleted" Grid.Row="4" Grid.Column="2" VerticalAlignment="Center" IsEnabled="False" />
|
||||
<xctk:CheckComboBox x:Name="comboBoxParticipantType" Grid.Row="5" Grid.Column="2" Margin="2" SelectedValue="Key" DisplayMemberPath="Value" />
|
||||
<TextBox x:Name="textBoxParticipantCreated" Grid.Row="6" IsReadOnly="True" IsEnabled="False" Grid.Column="2" Margin="2" VerticalContentAlignment="Center" />
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="7" Grid.Column="0">
|
||||
@ -167,7 +167,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<ListBox x:Name="listBoxUser" Margin="2" Grid.RowSpan="9" SelectionChanged="listBoxUser_SelectionChanged">
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<ContextMenu Name="contextMenuUser">
|
||||
<MenuItem x:Name="menuItemNewUser" Header="New.." Click="menuItemNewUser_Click">
|
||||
<MenuItem.Icon>
|
||||
<Image Source="Resources/add.png" />
|
||||
|
||||
@ -61,6 +61,8 @@ namespace RoleEditor
|
||||
|
||||
// load all participants
|
||||
List<Participant> participants = await Participant.LoadAll(_dbManager);
|
||||
participants.Sort((x, y) => string.Compare(x.Name, y.Name));
|
||||
|
||||
foreach (Participant p in participants)
|
||||
{
|
||||
_participants.Add(p);
|
||||
@ -465,8 +467,8 @@ namespace RoleEditor
|
||||
this.textBoxParticipantStreet.Text = (p != null) ? p.Street : string.Empty;
|
||||
this.textBoxParticipantPostalCode.Text = (p != null) ? p.PostalCode : string.Empty;
|
||||
this.textBoxParticipantCity.Text = (p != null) ? p.City : string.Empty;
|
||||
// this.checkboxParticipantActive.Checked = (p != null) ? p.
|
||||
this.textBoxParticipantCreated.Text = (p != null) ? p.Created.ToString() : string.Empty;
|
||||
this.checkboxParticipantDeleted.IsChecked = (p != null) ? p.Deleted : null;
|
||||
this.textBoxParticipantModified.Text = (p != null) ? p.Modified.ToString() : string.Empty;
|
||||
this.checkBoxParticipantAllowBSMD.IsChecked = (p != null) ? p.IsFlagSet(Participant.ParticipantFlags.ALLOW_BSMD) : null;
|
||||
this.comboBoxParticipantType.SelectedItems.Clear();
|
||||
@ -510,6 +512,11 @@ namespace RoleEditor
|
||||
_assignedPorts.Add(pa);
|
||||
}
|
||||
}
|
||||
|
||||
this.contextMenuUser.IsEnabled = !p.Deleted;
|
||||
this.buttonAddPortAssignment.IsEnabled = !p.Deleted;
|
||||
this.buttonRemovePortAssignment.IsEnabled = !p.Deleted;
|
||||
|
||||
}
|
||||
|
||||
private async void listBoxRoles_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
@ -594,7 +601,7 @@ namespace RoleEditor
|
||||
if(this.listBoxParticipant.SelectedItem is Participant p)
|
||||
{
|
||||
await p.Delete(_dbManager);
|
||||
this._participants.Remove(p);
|
||||
p.Deleted = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -628,6 +635,7 @@ namespace RoleEditor
|
||||
{
|
||||
if (this.listBoxUser.SelectedItem is User u)
|
||||
{
|
||||
await u.ExecuteNonQuery(_dbManager); // extra history delete happens here
|
||||
await u.Delete(_dbManager);
|
||||
this._users.Remove(u);
|
||||
}
|
||||
|
||||
2
src/RoleEditor/Properties/Settings.Designer.cs
generated
2
src/RoleEditor/Properties/Settings.Designer.cs
generated
@ -26,7 +26,7 @@ namespace RoleEditor.Properties {
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_" +
|
||||
"devel;Port=33306")]
|
||||
"test;Port=33306")]
|
||||
public string ConnectionString {
|
||||
get {
|
||||
return ((string)(this["ConnectionString"]));
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<Profiles />
|
||||
<Settings>
|
||||
<Setting Name="ConnectionString" Type="System.String" Scope="Application">
|
||||
<Value Profile="(Default)">Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_devel;Port=33306</Value>
|
||||
<Value Profile="(Default)">Server=localhost;User ID=ds;Password=HalloWach_2323XXL!!;Database=bremen_calling_test;Port=33306</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows7.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationIcon>Resources\lock_preferences.ico</ApplicationIcon>
|
||||
@ -30,8 +30,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="ExcelDataReader" Version="3.7.0-develop00385" />
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.0" />
|
||||
<PackageReference Include="ExcelDataReader" Version="3.8.0" />
|
||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Data;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace brecal.model
|
||||
@ -42,6 +38,11 @@ namespace brecal.model
|
||||
/// <param name="cmd">CMD created by DB manager</param>
|
||||
public abstract void SetDelete(IDbCommand cmd);
|
||||
|
||||
public virtual void SetNonQuery(IDbCommand cmd)
|
||||
{
|
||||
// default: do nothing
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Each database entity must be able to save itself to the database
|
||||
/// </summary>
|
||||
@ -65,5 +66,10 @@ namespace brecal.model
|
||||
await manager.ExecuteNonQuery(this.SetDelete);
|
||||
}
|
||||
|
||||
public async Task ExecuteNonQuery(IDBManager manager)
|
||||
{
|
||||
await manager.ExecuteNonQuery(this.SetNonQuery);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,6 +55,8 @@ namespace brecal.model
|
||||
|
||||
public uint Flags { get; set; }
|
||||
|
||||
public bool Deleted { get; set; } = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region public static methods
|
||||
@ -83,6 +85,7 @@ namespace brecal.model
|
||||
if (!reader.IsDBNull(6)) p.Flags = (uint)reader.GetInt32(6);
|
||||
if (!reader.IsDBNull(7)) p.Created = reader.GetDateTime(7);
|
||||
if (!reader.IsDBNull(8)) p.Modified = reader.GetDateTime(8);
|
||||
if (!reader.IsDBNull(9)) p.Deleted = reader.GetBoolean(9);
|
||||
result.Add(p);
|
||||
}
|
||||
return result;
|
||||
@ -90,7 +93,7 @@ namespace brecal.model
|
||||
|
||||
public static void SetLoadQuery(IDbCommand cmd, params object?[] list)
|
||||
{
|
||||
cmd.CommandText = "SELECT id, name, street, postal_code, city, type, flags, created, modified FROM participant";
|
||||
cmd.CommandText = "SELECT id, name, street, postal_code, city, type, flags, created, modified, deleted FROM participant";
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -111,7 +114,7 @@ namespace brecal.model
|
||||
|
||||
public override void SetDelete(IDbCommand cmd)
|
||||
{
|
||||
cmd.CommandText = "DELETE FROM participant WHERE id = @ID";
|
||||
cmd.CommandText = "UPDATE participant SET deleted = 1 WHERE id = @ID";
|
||||
|
||||
IDataParameter idParam = cmd.CreateParameter();
|
||||
idParam.ParameterName = "ID";
|
||||
|
||||
@ -101,6 +101,16 @@ namespace brecal.model
|
||||
return this.Username ?? $"{base.Id} - {this.GetType().Name}";
|
||||
}
|
||||
|
||||
public override void SetNonQuery(IDbCommand cmd)
|
||||
{
|
||||
cmd.CommandText = "UPDATE history set user_id = NULL WHERE user_id = @ID";
|
||||
|
||||
IDataParameter idParam = cmd.CreateParameter();
|
||||
idParam.ParameterName = "ID";
|
||||
idParam.Value = this.Id;
|
||||
cmd.Parameters.Add(idParam);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region private methods
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MySqlConnector" Version="2.3.0-beta.1" />
|
||||
<PackageReference Include="MySqlConnector" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -69,7 +69,7 @@ def create_app(test_config=None, instance_path=None):
|
||||
app.register_blueprint(history.bp)
|
||||
app.register_blueprint(ports.bp)
|
||||
|
||||
logging.basicConfig(filename='brecal.log', level=logging.WARNING, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')
|
||||
logging.basicConfig(filename='brecaltest.log', level=logging.DEBUG, format='%(asctime)s | %(name)s | %(levelname)s | %(message)s')
|
||||
local_db.initPool(os.path.dirname(app.instance_path))
|
||||
logging.info('App started')
|
||||
|
||||
|
||||
@ -281,10 +281,8 @@ class SQLQuery():
|
||||
|
||||
def get_next24hrs_shipcalls()->str:
|
||||
query = ("SELECT s.id as id, ship.name as name FROM shipcall s INNER JOIN ship ON s.ship_id = ship.id LEFT JOIN times t on t.shipcall_id = s.id AND t.participant_type = 8 " + \
|
||||
"WHERE (type = 1 AND ((t.id IS NOT NULL AND t.eta_berth >= NOW() AND t.eta_berth < (NOW() + INTERVAL 1 DAY))" + \
|
||||
"OR (eta >= NOW() AND eta < (NOW() + INTERVAL 1 DAY)))) OR " + \
|
||||
"((type = 2 OR type = 3) AND ((t.id IS NOT NULL AND t.etd_berth >= NOW() AND " + \
|
||||
"t.etd_berth < (NOW() + INTERVAL 1 DAY)) OR (etd >= NOW() AND etd < (NOW() + INTERVAL 1 DAY))))" + \
|
||||
"WHERE (type = 1 AND (COALESCE(t.eta_berth, eta) >= NOW() AND COALESCE(t.eta_berth, eta) < (NOW() + INTERVAL 1 DAY)))" + \
|
||||
"OR ((type = 2 OR type = 3) AND (COALESCE(t.etd_berth, etd) >= NOW() AND COALESCE(t.etd_berth, etd) < (NOW() + INTERVAL 1 DAY)))"
|
||||
"AND s.canceled = 0")
|
||||
return query
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ from .. import local_db
|
||||
from ..services import jwt_handler
|
||||
|
||||
|
||||
|
||||
def GetUser(options):
|
||||
|
||||
pooledConnection = None
|
||||
|
||||
@ -57,7 +57,7 @@ def initPool(instancePath, connection_filename="connection_data_prod.json",
|
||||
credentials_file = "email_credentials_test.json"
|
||||
credentials_path = os.path.join(instancePath, f'../../../secure/{credentials_file}')
|
||||
|
||||
# credentials_path = 'C:\\temp\\email_credentials_test.json'
|
||||
# credentials_path = "E:/temp/email_credentials_devel.json"
|
||||
|
||||
if not os.path.exists(credentials_path):
|
||||
print('cannot find ' + os.path.abspath(credentials_path))
|
||||
|
||||
@ -3,49 +3,42 @@
|
||||
"type" : 1,
|
||||
"color" : "#0867ec",
|
||||
"name" : "assignment",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Nominierung"
|
||||
},
|
||||
{
|
||||
"type" : 2,
|
||||
"color" : "#ea5c00",
|
||||
"name" : "next24h",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Morgenrunde relevant"
|
||||
},
|
||||
{
|
||||
"type" : 3,
|
||||
"color" : "#f34336",
|
||||
"name" : "time_conflict",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Zeitlicher Konflikt"
|
||||
},
|
||||
{
|
||||
"type" : 4,
|
||||
"color" : "#28b532",
|
||||
"name" : "time_conflict_resolved",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Zeitlicher Konflikt gelöst"
|
||||
},
|
||||
{
|
||||
"type" : 5,
|
||||
"color" : "#a8a8a8",
|
||||
"name" : "unassigned",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Nominierung abgewählt"
|
||||
},
|
||||
{
|
||||
"type" : 6,
|
||||
"color" : "#a8a800",
|
||||
"name" : "missing_data",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Fehlende Daten"
|
||||
},
|
||||
{
|
||||
"type" : 7,
|
||||
"color" : "#808070",
|
||||
"name" : "cancelled",
|
||||
"link" : "https://www.bremen-calling.de/",
|
||||
"msg_text" : "Storno"
|
||||
}
|
||||
]
|
||||
@ -38,6 +38,9 @@ class EmailHandler():
|
||||
|
||||
self.server = smtplib.SMTP_SSL(self.mail_server, self.mail_port) # alternatively, SMTP
|
||||
|
||||
# set the following to 0 to avoid log spamming
|
||||
self.server.set_debuglevel(1) # 0: no debug, 1: debug
|
||||
|
||||
def check_state(self):
|
||||
"""check, whether the server login took place and is open."""
|
||||
try:
|
||||
|
||||
@ -124,11 +124,11 @@ def SendEmails(email_dict):
|
||||
defs.message_types = json.load(f)
|
||||
f.close()
|
||||
|
||||
for user, notifications in email_dict.items():
|
||||
for user_email, notifications in email_dict.items():
|
||||
msg = EmailMessage()
|
||||
msg["Subject"] = '[Bremen calling] Notification'
|
||||
msg["From"] = defs.email_credentials["sender"]
|
||||
msg["To"] = user.user_email
|
||||
msg["To"] = user_email
|
||||
|
||||
with open(os.path.join(current_path,'../msg/notification_template.html'), mode="r", encoding="utf-8") as file:
|
||||
body = file.read()
|
||||
@ -145,7 +145,8 @@ def SendEmails(email_dict):
|
||||
with open(os.path.join(current_path,'../msg/notification_element.html'), mode="r", encoding="utf-8") as file:
|
||||
element = file.read()
|
||||
element = element.replace("[[color]]", message_type["color"])
|
||||
element = element.replace("[[link]]", message_type["link"])
|
||||
linktext = defs.email_credentials["url_template"] + str(notification.shipcall_id)
|
||||
element = element.replace("[[link]]", linktext)
|
||||
|
||||
# We want to show the following information for each notification:
|
||||
# Ship-name, Arr/Dep/Shift, ETA/ETD, berth
|
||||
@ -180,7 +181,7 @@ def SendEmails(email_dict):
|
||||
body = body.replace("[[NOTIFICATION_ELEMENTS]]", replacement)
|
||||
msg.set_content(body, subtype='html', charset='utf-8', cte='8bit')
|
||||
|
||||
conn.sendmail(defs.email_credentials["sender"], user.user_email, msg.as_string())
|
||||
conn.sendmail(defs.email_credentials["sender"], user_email, msg.as_string())
|
||||
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
@ -210,10 +211,10 @@ def SendNotifications():
|
||||
email_dict = dict()
|
||||
users_dict = dict()
|
||||
user_query = "SELECT * from user"
|
||||
users = commands.query(user_query, model=model.User)
|
||||
users = commands.query(user_query)
|
||||
for participant in participants:
|
||||
for user in users:
|
||||
if user.participant_id == participant.id:
|
||||
if user["participant_id"] == participant.id:
|
||||
if not participant.id in users_dict:
|
||||
users_dict[participant.id] = []
|
||||
users_dict[participant.id].append(user)
|
||||
@ -225,31 +226,37 @@ def SendNotifications():
|
||||
p_query = "SELECT * from shipcall_participant_map where shipcall_id = ?id?"
|
||||
assigned_participants = commands.query(p_query, model=model.ShipcallParticipantMap, param={"id":notification.shipcall_id})
|
||||
for assigned_participant in assigned_participants:
|
||||
if not assigned_participant.participant_id in users_dict:
|
||||
continue
|
||||
users = users_dict[assigned_participant.participant_id]
|
||||
for user in users:
|
||||
# send notification to user
|
||||
if user.notify_email:
|
||||
if user not in email_dict:
|
||||
email_dict[user] = []
|
||||
email_dict[user].append(notification)
|
||||
if user.notify_whatsapp:
|
||||
if user["notify_email"]:
|
||||
if user["user_email"] not in email_dict:
|
||||
email_dict[user["user_email"]] = []
|
||||
if notification not in email_dict[user["user_email"]]:
|
||||
email_dict[user["user_email"]].append(notification)
|
||||
if user["notify_whatsapp"]:
|
||||
# TBD
|
||||
pass
|
||||
if user.notify_signal:
|
||||
if user["notify_signal"]:
|
||||
# TBD
|
||||
pass
|
||||
else:
|
||||
if notification.participant_id in users_dict:
|
||||
users = users_dict[notification.participant_id]
|
||||
for user in users:
|
||||
user_notifications = model.bitflag_to_list(user["notify_event"])
|
||||
# send notification to user
|
||||
if user.notify_email and user.wants_notifications(notification.type):
|
||||
if user not in email_dict:
|
||||
email_dict[user] = []
|
||||
email_dict[user].append(notification)
|
||||
if user.notify_whatsapp and user.wants_notifications(notification.type):
|
||||
if user["notify_email"] and notification.type in user_notifications:
|
||||
if user["user_email"] not in email_dict:
|
||||
email_dict[user["user_email"]] = []
|
||||
if notification not in email_dict[user["user_email"]]:
|
||||
email_dict[user["user_email"]].append(notification)
|
||||
if user["notify_whatsapp"] and notification.type in user_notifications:
|
||||
# TBD
|
||||
pass
|
||||
if user.notify_signal and user.wants_notifications(notification.type):
|
||||
if user["notify_signal"] and notification.type in user_notifications:
|
||||
# TBD
|
||||
pass
|
||||
|
||||
|
||||
31
src/server/BreCal/validators/input_validation_base.py
Normal file
31
src/server/BreCal/validators/input_validation_base.py
Normal file
@ -0,0 +1,31 @@
|
||||
import typing
|
||||
from marshmallow import ValidationError
|
||||
|
||||
class InputValidationBase:
|
||||
"""
|
||||
Base class for input validators. Common validation methods are grouped here.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def check_required_fields(content:dict, required_fields:list[str]):
|
||||
missing_fields = [field for field in required_fields if content.get(field) is None]
|
||||
if missing_fields:
|
||||
raise ValidationError({"required_fields": f"Missing required fields: {missing_fields}"})
|
||||
|
||||
@staticmethod
|
||||
def check_if_entry_is_already_deleted(entry:dict):
|
||||
"""
|
||||
Checks if the entry has 'deleted' set to True/1.
|
||||
"""
|
||||
if entry.get("deleted") in [True, 1, "1"]:
|
||||
raise ValidationError({"deleted": "The selected entry is already deleted."})
|
||||
|
||||
@staticmethod
|
||||
def check_deleted_flag_on_post(content:dict):
|
||||
"""
|
||||
Checks if 'deleted' is set to 1/True in a POST (Create) request.
|
||||
"""
|
||||
if content.get("deleted") in [True, 1, "1"]:
|
||||
raise ValidationError({"deleted": "Cannot create an entry with 'deleted' set to 1."})
|
||||
|
||||
|
||||
@ -18,10 +18,11 @@ from BreCal.validators.input_validation_utils import check_if_user_is_bsmd_type,
|
||||
from BreCal.database.sql_handler import execute_sql_query_standalone
|
||||
from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag
|
||||
from BreCal.validators.validation_base_utils import check_if_string_has_special_characters
|
||||
from BreCal.validators.input_validation_base import InputValidationBase
|
||||
|
||||
import werkzeug
|
||||
|
||||
class InputValidationShip():
|
||||
class InputValidationShip(InputValidationBase):
|
||||
"""
|
||||
This class combines a complex set of individual input validation functions into a joint object.
|
||||
It uses static methods, so the object does not need to be instantiated, but functions can be called immediately.
|
||||
@ -55,6 +56,13 @@ class InputValidationShip():
|
||||
|
||||
# 3.) Check for reasonable Values (see BreCal.schemas.model.ShipSchema)
|
||||
InputValidationShip.optionally_evaluate_bollard_pull_value(content)
|
||||
|
||||
# 4.) No deleted flag may be set on POST
|
||||
InputValidationShip.check_deleted_flag_on_post(content)
|
||||
|
||||
# 5.) Check if is_tug is null
|
||||
InputValidationShip.check_is_tug_null(content)
|
||||
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
@ -70,6 +78,10 @@ class InputValidationShip():
|
||||
|
||||
# 4.) Check for reasonable Values (see BreCal.schemas.model.ShipSchema)
|
||||
InputValidationShip.optionally_evaluate_bollard_pull_value(content)
|
||||
|
||||
# 5.) Check if tug is null
|
||||
InputValidationShip.check_is_tug_null(content)
|
||||
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
@ -159,5 +171,11 @@ class InputValidationShip():
|
||||
raise ValidationError({"deleted":f"The selected ship entry is already deleted."})
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def check_is_tug_null(content:dict):
|
||||
is_tug = content.get("is_tug", None)
|
||||
if is_tug is None:
|
||||
raise ValidationError({"is_tug":f"The 'is_tug' property must be set to either True or False."})
|
||||
return
|
||||
|
||||
|
||||
|
||||
@ -17,12 +17,13 @@ from BreCal.database.sql_handler import get_assigned_participant_of_type
|
||||
from BreCal.database.sql_handler import execute_sql_query_standalone
|
||||
from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag
|
||||
from BreCal.validators.validation_base_utils import check_if_string_has_special_characters
|
||||
from BreCal.validators.input_validation_base import InputValidationBase
|
||||
from BreCal.database.sql_queries import SQLQuery
|
||||
import werkzeug
|
||||
|
||||
|
||||
|
||||
class InputValidationShipcall():
|
||||
class InputValidationShipcall(InputValidationBase):
|
||||
"""
|
||||
This class combines a complex set of individual input validation functions into a joint object.
|
||||
It uses static methods, so the object does not need to be instantiated, but functions can be called immediately.
|
||||
@ -60,7 +61,11 @@ class InputValidationShipcall():
|
||||
InputValidationShipcall.check_participant_list_not_empty_when_user_is_agency(loadedModel)
|
||||
|
||||
# check for reasonable values in the shipcall fields
|
||||
InputValidationShipcall.check_shipcall_values(loadedModel, content, forbidden_keys=["evaluation", "evaluation_message"]) # "canceled"
|
||||
InputValidationShipcall.check_shipcall_values(loadedModel, content, forbidden_keys=["evaluation", "evaluation_message", "canceled"]) # "canceled"
|
||||
|
||||
# check for deleted flag on POST
|
||||
InputValidationShipcall.check_deleted_flag_on_post(content)
|
||||
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
|
||||
@ -17,6 +17,7 @@ from BreCal.database.sql_queries import SQLQuery
|
||||
from BreCal.database.sql_handler import execute_sql_query_standalone
|
||||
from BreCal.database.sql_handler import get_assigned_participant_of_type
|
||||
from BreCal.database.sql_utils import get_times_data_for_id
|
||||
from BreCal.validators.input_validation_base import InputValidationBase
|
||||
from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag, check_if_string_has_special_characters
|
||||
import werkzeug
|
||||
|
||||
@ -63,7 +64,7 @@ def build_post_data_type_dependent_required_fields_dict()->dict[ShipcallType,dic
|
||||
|
||||
|
||||
|
||||
class InputValidationTimes():
|
||||
class InputValidationTimes(InputValidationBase):
|
||||
"""
|
||||
This class combines a complex set of individual input validation functions into a joint object.
|
||||
It uses static methods, so the object does not need to be instantiated, but functions can be called immediately.
|
||||
@ -92,6 +93,10 @@ class InputValidationTimes():
|
||||
|
||||
# 4.) Value checking
|
||||
InputValidationTimes.check_dataset_values(user_data, loadedModel, content)
|
||||
|
||||
# 5.) Deleted flag may not be set on POST
|
||||
InputValidationTimes.check_deleted_flag_on_post(content)
|
||||
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
|
||||
@ -59,7 +59,7 @@ def create_validation_error_response(ex:ValidationError, status_code:int=400, cr
|
||||
|
||||
if create_log:
|
||||
logging.warning(ex) if ex is not None else logging.warning(message)
|
||||
print(ex) if ex is not None else print(message)
|
||||
# print(ex) if ex is not None else print(message)
|
||||
return (serialized_response, status_code)
|
||||
|
||||
def create_werkzeug_error_response(ex:Forbidden, status_code:int=403, create_log:bool=True)->typing.Tuple[str,int]:
|
||||
@ -71,7 +71,7 @@ def create_werkzeug_error_response(ex:Forbidden, status_code:int=403, create_log
|
||||
|
||||
if create_log:
|
||||
logging.warning(ex) if ex is not None else logging.warning(message)
|
||||
print(ex) if ex is not None else print(message)
|
||||
# print(ex) if ex is not None else print(message)
|
||||
return serialized_response, status_code
|
||||
|
||||
def create_dynamic_exception_response(ex, status_code:int=400, message:typing.Optional[str]=None, create_log:bool=True):
|
||||
@ -83,5 +83,5 @@ def create_dynamic_exception_response(ex, status_code:int=400, message:typing.Op
|
||||
|
||||
if create_log:
|
||||
logging.warning(ex) if ex is not None else logging.warning(message)
|
||||
print(ex) if ex is not None else print(message)
|
||||
# print(ex) if ex is not None else print(message)
|
||||
return (serialized_response, status_code)
|
||||
|
||||
@ -52,6 +52,7 @@ class ValidationRules(ValidationRuleFunctions):
|
||||
# 'translate' all error codes into readable, human-understandable format.
|
||||
evaluation_results = [(state, self.describe_error_message(msg)) for (state, msg) in evaluation_results]
|
||||
|
||||
if evaluation_results:
|
||||
logging.info(f"Validation results for shipcall {shipcall.id}: {evaluation_results}")
|
||||
|
||||
# check, what the maximum state flag is and return it
|
||||
|
||||
@ -2,7 +2,7 @@ import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
sys.path.insert(0, '/var/www/brecal/src/server')
|
||||
sys.path.insert(0, '/var/www/brecal_test/src/server')
|
||||
sys.path.insert(0, '/var/www/venv/lib/python3.12/site-packages/')
|
||||
|
||||
import schedule
|
||||
|
||||
Loading…
Reference in New Issue
Block a user