Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F112704
device-list-tracker.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
device-list-tracker.cpp
View Options
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include
<libkazv-config.hpp>
#include
"device-list-tracker.hpp"
#include
<algorithm>
#include
<zug/transducer/filter.hpp>
#include
<zug/sequence.hpp>
#include
<zug/transducer/distinct.hpp>
#include
<zug/transducer/chain.hpp>
#include
<debug.hpp>
namespace
Kazv
{
immer
::
flex_vector
<
std
::
string
>
DeviceListTracker
::
outdatedUsers
()
const
{
return
intoImmer
(
immer
::
flex_vector
<
std
::
string
>
{},
zug
::
filter
([](
auto
n
)
{
auto
[
userId
,
outdated
]
=
n
;
return
outdated
;
})
|
zug
::
map
([](
auto
n
)
{
auto
[
userId
,
outdated
]
=
n
;
return
userId
;
}),
usersToTrackDeviceLists
);
}
bool
DeviceListTracker
::
addDevice
(
std
::
string
userId
,
std
::
string
deviceId
,
Api
::
QueryKeysJob
::
DeviceInformation
deviceInfo
,
Crypto
&
crypto
)
{
using
namespace
CryptoConstants
;
if
(
userId
!=
deviceInfo
.
userId
||
deviceId
!=
deviceInfo
.
deviceId
)
{
return
false
;
}
// if the ed25519 key changed, reject
auto
curEd25519Key
=
deviceInfo
.
keys
[
ed25519
+
":"
+
deviceId
];
if
(
deviceLists
[
userId
].
find
(
deviceId
)
&&
curEd25519Key
!=
deviceLists
[
userId
][
deviceId
].
ed25519Key
)
{
return
false
;
}
kzo
.
client
.
dbg
()
<<
"verifying device info"
<<
std
::
endl
;
if
(
crypto
.
verify
(
deviceInfo
,
userId
,
deviceId
,
curEd25519Key
))
{
kzo
.
client
.
dbg
()
<<
"passed verification"
<<
std
::
endl
;
auto
info
=
DeviceKeyInfo
{
deviceId
,
deviceInfo
.
keys
[
ed25519
+
":"
+
deviceId
],
deviceInfo
.
keys
[
curve25519
+
":"
+
deviceId
],
deviceInfo
.
unsignedData
?
deviceInfo
.
unsignedData
.
value
().
deviceDisplayName
:
std
::
nullopt
};
deviceLists
=
std
::
move
(
deviceLists
)
.
update
(
userId
,
[
=
](
auto
deviceMap
)
{
return
std
::
move
(
deviceMap
).
set
(
deviceId
,
info
);
});
return
true
;
}
kzo
.
client
.
dbg
()
<<
"did not pass verification"
<<
std
::
endl
;
return
false
;
}
void
DeviceListTracker
::
markUpToDate
(
std
::
string
userId
)
{
usersToTrackDeviceLists
=
std
::
move
(
usersToTrackDeviceLists
).
set
(
userId
,
false
);
}
std
::
optional
<
DeviceKeyInfo
>
DeviceListTracker
::
get
(
std
::
string
userId
,
std
::
string
deviceId
)
const
{
try
{
return
deviceLists
.
at
(
userId
).
at
(
deviceId
);
}
catch
(
const
std
::
exception
&
)
{
return
std
::
nullopt
;
}
}
std
::
optional
<
DeviceKeyInfo
>
DeviceListTracker
::
findByEd25519Key
(
std
::
string
userId
,
std
::
string
ed25519Key
)
const
{
auto
devices
=
deviceLists
.
at
(
userId
);
auto
it
=
std
::
find_if
(
devices
.
begin
(),
devices
.
end
(),
[
=
](
auto
n
)
{
auto
[
deviceId
,
info
]
=
n
;
return
info
.
ed25519Key
==
ed25519Key
;
});
if
(
it
!=
devices
.
end
())
{
return
it
->
second
;
}
else
{
return
std
::
nullopt
;
}
}
std
::
optional
<
DeviceKeyInfo
>
DeviceListTracker
::
findByCurve25519Key
(
std
::
string
userId
,
std
::
string
curve25519Key
)
const
{
auto
devices
=
deviceLists
.
at
(
userId
);
auto
it
=
std
::
find_if
(
devices
.
begin
(),
devices
.
end
(),
[
=
](
auto
n
)
{
auto
[
deviceId
,
info
]
=
n
;
return
info
.
curve25519Key
==
curve25519Key
;
});
if
(
it
!=
devices
.
end
())
{
return
it
->
second
;
}
else
{
return
std
::
nullopt
;
}
}
static
bool
cryptographicallyEqual
(
DeviceKeyInfo
a
,
DeviceKeyInfo
b
)
{
a
.
displayName
=
std
::
nullopt
;
b
.
displayName
=
std
::
nullopt
;
a
.
trustLevel
=
Unseen
;
b
.
trustLevel
=
Unseen
;
return
std
::
move
(
a
)
==
std
::
move
(
b
);
}
static
bool
cryptographicallyEqual
(
const
DeviceListTracker
::
DeviceMapT
&
a
,
const
DeviceListTracker
::
DeviceMapT
&
b
)
{
auto
changed
=
false
;
auto
markChanged
=
[
&
changed
](
const
auto
&
)
{
changed
=
true
;
};
immer
::
diff
(
a
,
b
,
immer
::
make_differ
(
/* added = */
markChanged
,
/* removed = */
markChanged
,
/* changed = */
[
&
changed
](
const
auto
&
x
,
const
auto
&
y
)
{
if
(
!
cryptographicallyEqual
(
x
.
second
,
y
.
second
))
{
changed
=
true
;
}
}
));
return
!
changed
;
}
immer
::
flex_vector
<
std
::
string
>
DeviceListTracker
::
diff
(
DeviceListTracker
that
)
const
{
auto
users
=
zug
::
sequence
(
zug
::
map
([](
auto
n
)
{
return
n
.
first
;
}),
deviceLists
);
auto
thatUsers
=
zug
::
sequence
(
zug
::
map
([](
auto
n
)
{
return
n
.
first
;
}),
that
.
deviceLists
);
auto
changedUsers
=
intoImmer
(
immer
::
flex_vector
<
std
::
string
>
{},
zug
::
chain
(
std
::
move
(
thatUsers
))
|
zug
::
distinct
|
zug
::
filter
([
=
](
auto
userId
)
{
return
!
cryptographicallyEqual
(
deviceLists
[
userId
],
that
.
deviceLists
[
userId
]);
}),
std
::
move
(
users
));
return
changedUsers
;
}
auto
DeviceListTracker
::
devicesFor
(
std
::
string
userId
)
const
->
DeviceMapT
{
return
deviceLists
[
userId
];
}
bool
operator
==
(
DeviceKeyInfo
a
,
DeviceKeyInfo
b
)
{
return
a
.
deviceId
==
b
.
deviceId
&&
a
.
ed25519Key
==
b
.
ed25519Key
&&
a
.
curve25519Key
==
b
.
curve25519Key
&&
a
.
displayName
==
b
.
displayName
&&
a
.
trustLevel
==
b
.
trustLevel
;
}
bool
operator
!=
(
DeviceKeyInfo
a
,
DeviceKeyInfo
b
)
{
return
!
(
a
==
b
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 23, 10:19 PM (1 d, 1 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39164
Default Alt Text
device-list-tracker.cpp (5 KB)
Attached To
Mode
rL libkazv
Attached
Detach File
Event Timeline
Log In to Comment