Expose Matrix.User module
parent
ae19884a18
commit
259f695b74
2
elm.json
2
elm.json
|
@ -27,10 +27,12 @@
|
|||
"Internal.Values.Settings",
|
||||
"Internal.Values.StateManager",
|
||||
"Internal.Values.Timeline",
|
||||
"Internal.Values.User",
|
||||
"Internal.Values.Vault",
|
||||
"Matrix",
|
||||
"Matrix.Event",
|
||||
"Matrix.Settings",
|
||||
"Matrix.User",
|
||||
"Types"
|
||||
],
|
||||
"elm-version": "0.19.0 <= v < 0.20.0",
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
module Internal.Config.Text exposing
|
||||
( docs, failures, fields, mappings, logs
|
||||
( docs, failures, fields, mappings, logs, parses
|
||||
, accessTokenFoundLocally, accessTokenExpired, accessTokenInvalid
|
||||
, versionsFoundLocally, versionsReceived, versionsFailedToDecode
|
||||
, unsupportedVersionForEndpoint
|
||||
, decodedDictSize, invalidHashInHashdict, invalidHashInMashdict, leakingValueFound
|
||||
, parses
|
||||
)
|
||||
|
||||
{-| Throughout the Elm SDK, there are lots of pieces of text being used for
|
||||
|
@ -28,7 +27,7 @@ You should only do this if you know what you're doing.
|
|||
|
||||
## Type documentation
|
||||
|
||||
@docs docs, failures, fields, mappings, logs
|
||||
@docs docs, failures, fields, mappings, logs, parses
|
||||
|
||||
|
||||
## API Authentication
|
||||
|
@ -487,23 +486,6 @@ leakingValueFound leaking_value =
|
|||
"Found leaking value : " ++ leaking_value
|
||||
|
||||
|
||||
parses :
|
||||
{ reservedIPs :
|
||||
{ ipv6Toipv4 : String
|
||||
, multicast : String
|
||||
, futureUse : String
|
||||
, unspecified : String
|
||||
}
|
||||
}
|
||||
parses =
|
||||
{ reservedIPs =
|
||||
{ ipv6Toipv4 = "Detected a reserved ip address that is formerly used as an IPv6 to IPv4 relay. It is unlikely that this IP Address is real."
|
||||
, multicast = "Detected a reserved ip address that is used for multicasting. It is unlikely that this IP Address is real."
|
||||
, futureUse = "Detected a reserves ip address that is reserved for future use. It is unlikely that this IP Address is real if you're running a recent version of the Elm SDK."
|
||||
, unspecified = "This is an unspecified ip address. It is unlikely that this IP Address is real and someone might try to break something."
|
||||
}
|
||||
}
|
||||
|
||||
{-| These logs might appear during a process where something unexpected has
|
||||
happened. Most of these unexpected results, are taken account of by the Elm SDK,
|
||||
but logged so that the programmer can do something about it.
|
||||
|
@ -533,6 +515,28 @@ mappings =
|
|||
}
|
||||
|
||||
|
||||
{-| Logs for issues that might be found while parsing strings into meaningful data.
|
||||
-}
|
||||
parses :
|
||||
{ historicalUserId : String -> String
|
||||
, reservedIPs :
|
||||
{ ipv6Toipv4 : String
|
||||
, multicast : String
|
||||
, futureUse : String
|
||||
, unspecified : String
|
||||
}
|
||||
}
|
||||
parses =
|
||||
{ historicalUserId = \name -> "Found a historical username `" ++ name ++ "`."
|
||||
, reservedIPs =
|
||||
{ ipv6Toipv4 = "Detected a reserved ip address that is formerly used as an IPv6 to IPv4 relay. It is unlikely that this IP Address is real."
|
||||
, multicast = "Detected a reserved ip address that is used for multicasting. It is unlikely that this IP Address is real."
|
||||
, futureUse = "Detected a reserves ip address that is reserved for future use. It is unlikely that this IP Address is real if you're running a recent version of the Elm SDK."
|
||||
, unspecified = "This is an unspecified ip address. It is unlikely that this IP Address is real and someone might try to break something."
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{-| The Matrix homeserver can specify how it wishes to communicate, and the Elm
|
||||
SDK aims to communicate accordingly. This may fail in some scenarios, however,
|
||||
in which case it will throw this error.
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
module Internal.Values.User exposing
|
||||
( User, toString, fromString
|
||||
, localpart, domain
|
||||
)
|
||||
|
||||
{-| The Matrix user is uniquely identified by their identifier. This User type
|
||||
helps identify and safely handle these strings to transform them into meaningful
|
||||
data types.
|
||||
|
||||
|
||||
## User
|
||||
|
||||
@docs User, toString, fromString
|
||||
|
||||
|
||||
## Divide
|
||||
|
||||
Matrix users are identified by their unique ID. In the Matrix API, this is a
|
||||
string that looks as follows:
|
||||
|
||||
@alice:example.org
|
||||
\---/ \---------/
|
||||
| |
|
||||
| |
|
||||
localpart domain
|
||||
|
||||
Since the username is safely parsed, one can get these parts of the username.
|
||||
|
||||
@docs localpart, domain
|
||||
|
||||
-}
|
||||
|
||||
import Internal.Grammar.ServerName as ServerName
|
||||
import Internal.Grammar.UserId as UserId
|
||||
|
||||
|
||||
{-| The Matrix user represents a user across multiple Matrix rooms.
|
||||
-}
|
||||
type alias User =
|
||||
UserId.UserID
|
||||
|
||||
|
||||
{-| The domain represents the Matrix homeserver controlling this user. It also
|
||||
offers other Matrix homeservers an indication of where to look if you wish to
|
||||
send a message to this user.
|
||||
-}
|
||||
domain : User -> String
|
||||
domain =
|
||||
.domain >> ServerName.toString
|
||||
|
||||
|
||||
{-| Parse a string and convert it into a User, if formatted properly.
|
||||
-}
|
||||
fromString : String -> Maybe User
|
||||
fromString =
|
||||
UserId.fromString
|
||||
|
||||
|
||||
{-| The localpart is similar to a username, in the sense that every user has
|
||||
their own localpart. The localpart is not unique across multiple servers,
|
||||
however! There can be a user @alice:example.com and a user @alice:example.org in
|
||||
a room at the same time.
|
||||
-}
|
||||
localpart : User -> String
|
||||
localpart =
|
||||
.localpart
|
||||
|
||||
|
||||
{-| Convert a user into its unique identifier string value.
|
||||
-}
|
||||
toString : User -> String
|
||||
toString =
|
||||
UserId.toString
|
|
@ -0,0 +1,147 @@
|
|||
module Matrix.User exposing
|
||||
( User, toString
|
||||
, localpart, domain
|
||||
, get
|
||||
)
|
||||
|
||||
{-| Matrix users are identified by their unique ID. In the Matrix API, this is a
|
||||
string that looks as follows:
|
||||
|
||||
@alice:example.org
|
||||
\---/ \---------/
|
||||
| |
|
||||
| |
|
||||
localpart domain
|
||||
|
||||
Since it is very easy to abuse Matrix user IDs to sneak in arbitrary values,
|
||||
the Elm SDK parses them and makes sure they are safe. As a result, you might
|
||||
need this module to get the right information from a user!
|
||||
|
||||
|
||||
## User
|
||||
|
||||
@docs User, toString
|
||||
|
||||
|
||||
## Info
|
||||
|
||||
Sometimes, you are more interested in the username itself. These functions can
|
||||
help you decipher, disambiguate and categorize users based on their username.
|
||||
|
||||
@docs localpart, domain
|
||||
|
||||
|
||||
## Manipulate
|
||||
|
||||
@docs get
|
||||
|
||||
-}
|
||||
|
||||
import Internal.Values.Envelope as Envelope
|
||||
import Internal.Values.User as Internal
|
||||
import Types exposing (User(..))
|
||||
|
||||
|
||||
{-| The User type represents a Matrix user.
|
||||
|
||||
It contains information like:
|
||||
|
||||
- Their username on Matrix
|
||||
- The server that hosts their account
|
||||
- Access tokens needed to talk to the server
|
||||
|
||||
It does **NOT** contain information like:
|
||||
|
||||
- Their nickname
|
||||
- Their profile picture
|
||||
- Your private room with them
|
||||
|
||||
You can get all that information by looking it up in the [Vault](Matrix#Vault).
|
||||
|
||||
**Note:** Please do not store this user type as a variable in your model! You
|
||||
should always maintain a single source of truth in Elm, and the User type
|
||||
contains various credentials and API tokens that might expire if you don't
|
||||
update them from the Vault.
|
||||
|
||||
If you need to remember specific users, you can best compare their identifying
|
||||
string using [toString](Matrix-User#toString) or you can use
|
||||
[get](Matrix-User#get) with the Vault to get the user type.
|
||||
|
||||
-}
|
||||
type alias User =
|
||||
Types.User
|
||||
|
||||
|
||||
{-| The domain is the name of the server that the user connects to. Server names
|
||||
are case-sensitive, so if the strings are equal, the users are on the same
|
||||
server!
|
||||
|
||||
As a result, you can use the user domain for:
|
||||
|
||||
- When multiple users in a room have the same localpart on different servers
|
||||
- Finding other users from a potentially malicious homeserver
|
||||
- Counting homeservers in a room
|
||||
|
||||
See the following examples:
|
||||
|
||||
domain (get vault "@alice:example.org") -- "example.org"
|
||||
|
||||
domain (get vault "@bob:127.0.0.1") -- "127.0.0.1"
|
||||
|
||||
domain (get vault "@charlie:[2001:db8::]") -- "[2001:db8::]"
|
||||
|
||||
-}
|
||||
domain : User -> String
|
||||
domain (User user) =
|
||||
Envelope.extract Internal.domain user
|
||||
|
||||
|
||||
{-| Get a specific user by their unique identifier.
|
||||
|
||||
The Vault is needed as an input because the `User` type also stores various
|
||||
credentials needed to talk to the Matrix API.
|
||||
|
||||
get vault "@alice:example.org" -- Just (User "alice" "example.org")
|
||||
|
||||
get vault "@bob:127.0.0.1" -- Just (User "bob" "127.0.0.1")
|
||||
|
||||
get vault "@charlie:[2001:db8::]" -- Just (User "charlie" "2001:db8::")
|
||||
|
||||
get vault "@evil:#mp#ss#bl#.c#m" -- Nothing
|
||||
|
||||
get vault "" -- Nothing
|
||||
|
||||
-}
|
||||
get : Types.Vault -> String -> Maybe User
|
||||
get (Types.Vault vault) username =
|
||||
Envelope.mapMaybe (\_ -> Internal.fromString username) vault
|
||||
|> Maybe.map Types.User
|
||||
|
||||
|
||||
{-| The localpart is the user's unique username. Every homeserver has their own
|
||||
username registry, so you might occasionally find distinct users with the same
|
||||
localpart.
|
||||
|
||||
The localpart is often used as a user's name in a room if they haven't set up
|
||||
a custom name.
|
||||
|
||||
See the following examples:
|
||||
|
||||
localpart (get vault "@alice:example.org") -- "alice"
|
||||
|
||||
localpart (get vault "@bob:127.0.0.1") -- "bob"
|
||||
|
||||
localpart (get vault "@charlie:[2001:db8::]") -- "charlie"
|
||||
|
||||
-}
|
||||
localpart : User -> String
|
||||
localpart (User user) =
|
||||
Envelope.extract Internal.localpart user
|
||||
|
||||
|
||||
{-| Get the uniquely identifying string for this user. Since the strings are
|
||||
case-sensitive, you can run a simple string comparison to compare usernames.
|
||||
-}
|
||||
toString : User -> String
|
||||
toString (User user) =
|
||||
Envelope.extract Internal.toString user
|
|
@ -1,4 +1,4 @@
|
|||
module Types exposing (Vault(..), Event(..))
|
||||
module Types exposing (Vault(..), Event(..), User(..))
|
||||
|
||||
{-| The Elm SDK uses a lot of records and values that are easy to manipulate.
|
||||
Yet, the [Elm design guidelines](https://package.elm-lang.org/help/design-guidelines#keep-tags-and-record-constructors-secret)
|
||||
|
@ -12,12 +12,13 @@ access their content directly.
|
|||
The opaque types are placed in a central module so all exposed modules can
|
||||
safely access all exposed data types without risking to create circular imports.
|
||||
|
||||
@docs Vault, Event
|
||||
@docs Vault, Event, User
|
||||
|
||||
-}
|
||||
|
||||
import Internal.Values.Envelope as Envelope
|
||||
import Internal.Values.Event as Event
|
||||
import Internal.Values.User as User
|
||||
import Internal.Values.Vault as Vault
|
||||
|
||||
|
||||
|
@ -27,6 +28,12 @@ type Event
|
|||
= Event (Envelope.Envelope Event.Event)
|
||||
|
||||
|
||||
{-| Opaque type for Matrix User
|
||||
-}
|
||||
type User
|
||||
= User (Envelope.Envelope User.User)
|
||||
|
||||
|
||||
{-| Opaque type for Matrix Vault
|
||||
-}
|
||||
type Vault
|
||||
|
|
Loading…
Reference in New Issue