Commit graph

1163 commits

Author SHA1 Message Date
Pere Lev
232a0cd4df
S2S: Implement project handlers, based on the Deck ones 2023-06-26 23:26:53 +03:00
Pere Lev
224c290b04
S2S: Project creation and following 2023-06-26 23:12:40 +03:00
Pere Lev
9d6bbfdf92
C2S: Project creation 2023-06-26 23:01:41 +03:00
Pere Lev
372fd35f2c
Project routes, handlers and creation UI 2023-06-26 22:02:54 +03:00
Pere Lev
3db602e3bd
DB entity for Project 2023-06-26 17:26:20 +03:00
Pere Lev
050e8d09bc
Vocabulary for Project 2023-06-26 17:25:56 +03:00
Pere Lev
cc87b6e17d
Port deck creation to the new actor system 2023-06-19 18:44:12 +03:00
Pere Lev
0bd2ca8d5d
DB: Allow actors to mark they've just been created by someone
This will be used for sending that someone a grant with Admin access
2023-06-19 11:38:25 +03:00
Pere Lev
6e8cedadd1
Client: Fix bug: Invite target isn't addressed 2023-06-19 10:38:22 +03:00
Pere Lev
581838e550
Support the 6 ForgeFed roles + launch repo/deck/loom actor upon creation 2023-06-17 21:35:00 +03:00
Pere Lev
c8c2106eab
UI: In deck collaborator list, have a Remove button for each 2023-06-17 01:27:28 +03:00
Pere Lev
58518811e3
UI for publishing a Remove 2023-06-17 00:39:02 +03:00
Pere Lev
9673887479
C2S Remove handler 2023-06-17 00:28:35 +03:00
Pere Lev
7b64ab56b1
S2S Remove handlers for Person and Deck 2023-06-16 23:42:50 +03:00
Pere Lev
928ad8f9a9
UI in deck collaborators list, for adding a new collaborator 2023-06-16 20:12:40 +03:00
Pere Lev
aaa92d8141
UI for publishing an Invite 2023-06-16 17:39:11 +03:00
Pere Lev
ffb5dadac7
Link C2S handler with ClientMsg Person actor handler & port inviteC 2023-06-16 17:15:15 +03:00
Pere Lev
a683185918
Actor system: Add support for C2S actor methods 2023-06-15 20:23:50 +03:00
Pere Lev
d33f272ede
Switch to converged handlers than handle both local and remote activities
I was writing a topicLocalInvite handler when I realized how cumbersome
it's becoming, to have separate handlers for local activities. While it
allows me to pick custom specific message names and parameters (which is
why I took that approach in the first place), it causes a lot of
duplication and complexity (because I have to write the remote-activity
handlers anyway; adding local ones doesn't reduce complexity).

So this commit switches the entire system to communicate only using
AP/FF activities, including between local actors.
2023-06-15 15:44:43 +03:00
Pere Lev
d5d6b0af61
On app start, launch only verified Persons 2023-06-10 10:56:02 +03:00
Pere Lev
a41356c261
Upon account verification, launch the Person actor 2023-06-10 10:51:01 +03:00
Pere Lev
59e99f405a
Deck: Port Join handler 2023-06-09 09:40:10 +03:00
Pere Lev
85f77fcac4
Deck: Port Invite handler 2023-06-08 15:38:09 +03:00
Pere Lev
9955a3c0ad
Deck: Port/write Accept, Reject, Follow, Undo 2023-06-07 10:15:30 +03:00
Pere Lev
d467626049
Person: Implement (trivial) Revoke handler 2023-06-05 12:38:08 +03:00
Pere Lev
b4ebd08c5a
Person: Port Undo{Follow} handler 2023-06-05 11:34:58 +03:00
Pere Lev
552ef760e6
Person: Port Reject{Follow} handler 2023-06-05 10:03:20 +03:00
Pere Lev
9b0622cd7a
Person: Port the Accept{Follow} handler 2023-06-05 09:43:28 +03:00
Pere Lev
b759b87d0f
Person: Implement (the quite trivial) Join handler 2023-05-30 22:21:51 +03:00
Pere Lev
4d8e5de8b8
Person: Port Invite and Follow handlers to new system 2023-05-30 22:02:11 +03:00
Pere Lev
cc135692c0
Web.ActivityPub: Add Grant 'allows' & 'delegates' fields 2023-05-30 14:34:37 +03:00
Pere Lev
621275e257
Verify integrity proof on remote activities coming into local inboxes
Limitations:

- Only jcs-eddsa-2022 is supported for now, can add more easily if
  needed
- Not verifying forwarded local activities, only remotely-authored ones
- Fetching key and actor with HTTP without using the DB cache, because
  the current cache system is deprecated and I haven't yet created the
  new one
2023-05-30 12:51:41 +03:00
Pere Lev
e8e587af26
Generate FEP-8b32 authenticity proofs when delivering activities
Limitations:

- Verification of proofs not implemeneted yet, just generation.
  Verification probably coming in the next commit.
- Only jcs-eddsa-2022 is supported. Can add more cryptosuites once
  they're updated for the requirements of the VC Data Integrity spec.
- Bug: The proofs aren't stored in the DB versions of outgoing activities, i.e.
  HTTP GETing an activity won't include the proof. Probably not urgent
  to fix. Ideally, change the whole PersistJSONObject/Envelope/etc.
  thing to allow to serialize the activity exactly once.
2023-05-30 09:48:21 +03:00
Pere Lev
ba02d62eb5
Web.ActivityPub: Add Grant startTime and endTime 2023-05-29 10:47:41 +03:00
Pere Lev
a22aeb85d0
Web.ActivityPub: Add grantResult field, with optional duration 2023-05-29 09:50:17 +03:00
Pere Lev
906b5e8f44
Update docs for darcs->git switch, and switch from darcs-rev to gitrev 2023-05-25 13:55:56 +03:00
fr33domlover
6786e2e0e1 Implement theater-based remote delivery and port personGrant 2023-05-24 22:17:14 +00:00
fr33domlover
c9db823c8c Implement actor-model system and start moving Person actor to it
This patch makes Vervis temporarily unusable, because all actors' inbox POST
handlers use the new system, but the actual federation handler code hasn't been
ported. The next patches will port all the S2S activities supported so far, as
well as C2S.
2023-04-29 10:40:44 +00:00
fr33domlover
72796a6bdc UI, S2S: Implement Join flow in S2S + deck devs page now lists join requests 2022-11-14 15:11:25 +00:00
fr33domlover
e4d7156cbc S2S: Implement repoUndoF, loomUndoF, personUndoF 2022-10-31 14:13:18 +00:00
fr33domlover
9b158c13cd S2S: Implement deckUndoF 2022-10-27 16:27:58 +00:00
fr33domlover
934c69daae UI, S2S: Re-implement and re-enable Push activity
- When pushing to a repo, a Push activity is now automatically published
- The 'actor' is now the repo, and 'attributedTo' specifies the person who
  pushed
- No need for 'context' in the Push anymore, since it's always the 'actor'
- 'target' now specifies the branch as a Branch object rather than URI (since
  Vervis doesn't keep AS2 objects for branches anymore)
- I deleted 'pushCommitsC' (from Vervis.API) because the code for preparing and
  pushing an activity is so simple with the new delivery API, doesn't need a
  dedicated pushCommitsC function
- The generated Push activity does generate an HTML summary, unlike all other
  generated activities (in which I removed the summary generating code); I'm
  still unsure whether to bring back those summaries (extra code to write, for
  a problematic feature that may become useless when the new UI comes)
2022-10-26 10:47:38 +00:00
fr33domlover
340d1eacb1 S2S: loomFollowF & repoFollowF 2022-10-26 05:25:44 +00:00
fr33domlover
ee3548a940 S2S: Re-implement and re-enable deckFollowF 2022-10-25 19:02:07 +00:00
fr33domlover
648204ef80 S2S: Implement loomResolveF, allowing to close MR without Applying 2022-10-25 18:49:19 +00:00
fr33domlover
756c2952f2 S2S: Re-implement and re-enable personFollowF 2022-10-25 18:02:06 +00:00
fr33domlover
f76e80c028 S2S: Re-implement and re-enable deckResolveF 2022-10-25 16:12:48 +00:00
fr33domlover
8f8354ea5e C2S: Re-implement and enable resolveC, followC, undoC 2022-10-25 04:54:56 +00:00
fr33domlover
fa7f765e2e DB: Remote Ticket.status field 2022-10-20 15:41:47 +00:00
fr33domlover
fdf6a83c40 DB, UI: Prepare DB schema for Join flow + display deck collaborators & invites 2022-10-20 12:53:54 +00:00
fr33domlover
eb342b47ed DB: Move new entity declarations to a new module Vervis.Migration.Entities 2022-10-19 09:06:38 +00:00
fr33domlover
6407aaf897 DB: Avoid bulk-selecting specific-actor records
When looking up a specfic actor record for a given ActorId, you're pretty much
guaranteed to find the actor if it exists, because there's 1 function in the
codebase that handles this. Whenever a new actor type is added, which is a rare
event, that function gets updated.

But when mass-selecting actors using Esqueleto? Then, you need to LeftOuterJoin
by yourself on each actor type. This is both ugly and error prone, because all
those places in the codebase need to be updated when adding an actor type. The
only downside is that it means O(n) DB queries instead of O(1).

Perhaps there's some elegant way to "add" the specific-actor Joins to a given
Esqueleto query. Something to do some other time, as an optimization, if the
need arises.
2022-10-18 16:05:33 +00:00
fr33domlover
118b787416 UI: New ticket/MR creation form + deck/loom navigation links 2022-10-17 15:08:00 +00:00
fr33domlover
d8c65930ca UI, DB: Switch ticket filter to use TicketResolve instead of TicketStatus 2022-10-16 23:44:16 +00:00
fr33domlover
7ddb79d78d DB: If no workflow exists, add a dummy one 2022-10-16 23:42:41 +00:00
fr33domlover
e638ff4117 UI: In ticket/MR pages, display when and by whom the ticket was resolved 2022-10-16 22:25:21 +00:00
fr33domlover
58ca5e998e UI: Redirect DeckR to DeckTicketsR 2022-10-16 22:24:41 +00:00
fr33domlover
b99d864429 UI, Web: Re-enable ticket/MR replies view and commenting forms/buttons 2022-10-16 20:34:00 +00:00
fr33domlover
d5e913d97a S2S: Implement loomCreateNoteF 2022-10-16 12:24:41 +00:00
fr33domlover
2e7f9ef5e6 S2S: Re-enable deckCreateNoteF 2022-10-16 12:14:30 +00:00
fr33domlover
71bceec18b C2S, S2S: Re-enable createNoteC and personCreateNoteF 2022-10-16 11:26:24 +00:00
fr33domlover
8424c76de7 Link to per-actor keys from actor documents
Per-actor keys are now fully supported in Vervis! Caveats:

- The HTTP Signature keys produced by Vervis are Ed25519 keys; software that
  expects only RSA keys will fail here
- Like instance keys, per-actor keys are currently served in separate
  documents, not embedded in the actor document; so software that expects
  embedded keys will fail here
2022-10-12 18:01:52 +00:00
fr33domlover
32c87e3839 Improve the AP async HTTP delivery API and per-actor key support
New iteration of the ActivityPub delivery implementation and interface.
Advantages over previous interface:

* When sending a ByteString body, the sender is explicitly passed as a
  parameter instead of JSON-parsing it out of the ByteString
* Clear 3 operations provided: Send, Resend and Forward
* Support for per-actor keys
* Actor-type-specific functions (e.g. deliverRemoteDB_D) removed
* Only the most high-level API is exposed to Activity handler code, making
  handler code more concise and clear

Also added in this patch:

* Foundation for per-actor key support
* 1 key per actor allowed in DB
* Disabled C2S and S2S handlers now un-exported for clarity
* Audience and capability parsing automatically done for all C2S handlers
* Audience and activity composition automatically done for Vervis.Client
  builder functions

Caveats:

* Actor documents still don't link to their per-actor keys; that should be the
  last piece to complete per-actor key support
* No moderation and anti-spam tools yet
* Delivery API doesn't yet have good integration of persistence layer, e.g.
  activity is separately encoded into bytestring for DB and for HTTP; this will
  be improved in the next iteration
* Periodic delivery now done in 3 separate steps, running sequentially; it
  simplifies the code, but may be changed for efficiency/robustness in the next
  iterations
* Periodic delivery collects per-actor keys in a
  1-DB-transaction-for-each-delivery fashion, rather than grabbing them in the
  big Esqueleto query (or keeping the signed output in the DB; this isn't done
  currently to allow for smooth actor key renewal)
* No support yet in the API for delivery where the actor key has already been
  fetched, rather than doing a DB transaction to grab it; such support would be
  just an optimization, so it's low-priority, but will be added in later
  iterations
2022-10-12 16:50:11 +00:00
fr33domlover
0cc1e20f85 UX: Don't redirect to referer after login
It causes first login after verification to redirect to registration page,
which is weird, and the default Yesod falue is False, so, switching back to
False
2022-09-28 14:10:20 +00:00
fr33domlover
861d7636bc UX: Don't require login for verifying email address 2022-09-28 14:09:10 +00:00
fr33domlover
0d1de1278b UI: Add settings option to change main UI color 2022-09-28 06:03:43 +00:00
fr33domlover
84b70aa7b3 UI: If MR is applied, don't do the canApply check and display "RESOLVED" 2022-09-27 18:11:13 +00:00
fr33domlover
088d166d13 Fix infinite loop in getBundleR 2022-09-27 18:08:59 +00:00
fr33domlover
c5b85d11a9 UI: Since getLoomR doesn't have UI, redirect to LoomClothsR 2022-09-27 10:52:31 +00:00
fr33domlover
587ae5e8cc Fix query error in getTicketSummaries 2022-09-27 10:49:32 +00:00
fr33domlover
ceb0d951c1 UI: Personal overview: List your repos, decks, looms 2022-09-27 08:04:55 +00:00
fr33domlover
323de5b114 UI, Doc: Update Vervis repo links, because the route structure changed 2022-09-27 04:49:17 +00:00
fr33domlover
ee26ef7b82 UI: Actor outbox view: Render URI from route instead of parsing JSON for @id 2022-09-26 14:20:21 +00:00
fr33domlover
7429345cc0 If an outbox item is missing an @id, display whole activity in error message 2022-09-26 13:52:01 +00:00
fr33domlover
a96fcb8835 PostReceiveR hook handler: Don't raise error, otherwise VCS push fails 2022-09-26 13:31:24 +00:00
fr33domlover
482e2e806e DB: Migration: When switching repos dir to new layout, remove old sharer dirs 2022-09-26 13:27:16 +00:00
fr33domlover
6b0783a10b DB: Migration: Fix error in mig 447, accidentally creation CollabTopicLocal
Repo/Loom/Deck created one in their migrations, but CollabTopicAccept isn't
itself a topic, it's just a helper, so it needs to *find* the relevant
CollabTopicLocal rather than create a new one.
2022-09-26 13:12:44 +00:00
fr33domlover
cc9facdf5a UI: Tweak and re-enable UI for uploading personal SSH keys 2022-09-26 12:51:06 +00:00
fr33domlover
206d140b95 DB: Migration: Check for surprisingly named foreign constraints, fail if found
Because finding them may be a sign of undetected error in the migration plan,
so it's best to stop and find it
2022-09-26 12:48:21 +00:00
fr33domlover
1d2a251c13 DB: Fix typo in DB migration 2022-09-26 06:55:23 +00:00
fr33domlover
6d0eab24d1 UI: Define nav breadcrumbs for all routes 2022-09-26 06:54:16 +00:00
fr33domlover
ab105cb604 Crypto: PersistField instance for ActorKey, preparing to support per-actor keys
Like the KeyFile instance, it stores just the secret key, in a plain
ByteString, and generates the public key from it when decoding from the DB
2022-09-25 12:29:53 +00:00
fr33domlover
f10655f2c1 Client, UI: "Apply" button for local MRs & PublishMergeR form for remote MRs 2022-09-24 21:15:40 +00:00
fr33domlover
ba6f22b94b S2S: Implement loomApplyF (remote person asking to apply bundle on local loom) 2022-09-24 15:46:02 +00:00
fr33domlover
be95f15b21 C2S: Implement applyC (apply a patch/MR to a repo/branch)
Both Git and Darcs are supported

- Darcs implementation applies right on the bare repo, I haven't tested to make
  sure it works right (federated MR demo is going to be only for Git)
- Git implementation clones to temporary repo, runs `git am` on it to apply,
  then pushes to the real bare repo (because `git am` doesn't work on bare
  repos; I haven't tested yet to see how it handles conflicts; cloning and
  pushing should be efficient since the refs are just hardlinked rather than
  copied)
2022-09-24 09:04:10 +00:00
fr33domlover
b5adfce971 S2S: loomOfferTicketF, open MR sent by remote author 2022-09-23 15:59:21 +00:00
fr33domlover
ef8e1c1108 S2S: deckOfferTicketF (i.e. local deck receives ticket from remote author) 2022-09-23 15:58:54 +00:00
fr33domlover
0d922b0e5a Client, UI: Git merge request submission form 2022-09-23 05:20:39 +00:00
fr33domlover
9cb90c58c0 DB: Remember whether a Bundle came from person input or auto-generated 2022-09-22 17:23:33 +00:00
fr33domlover
de51fb9ab5 C2S: offerTicketC: If origin provided but not bundle, generate patches from git
For now it's implemented only for Git:

If tracker is a local loom, and a (local or remote) origin repo is specified,
but no patches are provided, then generate them ourselves!

* Clone the (local) target repo
* Add the (local or remote) origin repo as a git remote
* Make sure target branch is an ancestor of the origin branch
* Generate patches for the commits that origin adds on top of target
* Insert them into our DB
2022-09-22 17:12:37 +00:00
fr33domlover
2e7c5f767c Add 'cloneUri' to AP.Repo, publish in getRepoR, grab in offerTicketC
In offerTicketC it can be used for fetching commits from the remote origin
repo, by knowing its clone URI

Only HTTP clone URIs are supported for now, because it's enough for finishing
the federated MR implementation. Apparently user@host:path isn't a valid URI
and I'll later add a parser for that
2022-09-22 06:02:14 +00:00
fr33domlover
e7ab9e701c C2S: offerTicketC: Add VCS-type and patch-type consistency checks 2022-09-21 17:45:38 +00:00
fr33domlover
23b5343ec2 C2S: Enable offerTicketC for person inbox post handler 2022-09-21 14:22:36 +00:00
fr33domlover
de2e29d505 C2S: offerTicketC re-enabled and supporting looms and remote origin repo
What's missing:

- Match patch VCS, origin repo VCS and target repo VCS
- Hook into postPersonInboxR
- If only origin is provided, generate patches / otherwise somehow remember the
  commits proposed
2022-09-21 12:50:26 +00:00
fr33domlover
0b10056cc3 UI: getClothR: If a Bundle exists in DB, display list of its patches 2022-09-19 12:02:48 +00:00
fr33domlover
ffe68390e5 UI: getBundleR: Display list of old versions and list of patches 2022-09-19 11:40:08 +00:00
fr33domlover
dae8554a12 UI: getPatchR: Display diff-syntax-highlighted patch content file 2022-09-19 11:00:47 +00:00
fr33domlover
5673340bd1 UI: Display origin and target repos in getClothR HTML 2022-09-18 17:37:25 +00:00
fr33domlover
9906231d04 DB, Web: Allow origin repo for Cloths, mention in getClothR JSON 2022-09-18 15:55:42 +00:00
fr33domlover
9deba96cf2 UI: Serve HTML in getClothR, copied from getTicketR 2022-09-18 07:44:00 +00:00
fr33domlover
1e2b3d2006 UI: HTML version for getLoomClothsR, copied from getDeckTicketsR 2022-09-17 19:17:11 +00:00
fr33domlover
1db56ced39 UI: Re-enable ticket page, some pieces still missing, mostly buttons 2022-09-17 17:42:04 +00:00
fr33domlover
e69d775f3f UI: Fix and re-enable deck ticket list view 2022-09-17 10:14:27 +00:00
fr33domlover
c495d78d05 C2S, UI: Loom creation and Repo linking to a Loom
RepoSourceR, for a repo that doesn't have a loom, lists looms that want to
serve that repo with buttons for bidirectionally linking the repo to a loom

Once linked, the repo navbar has a Patches/MRs link pointing to the LoomClothsR
of the linked Loom
2022-09-17 08:31:22 +00:00
fr33domlover
1c8c6d9d24 UI: In RepoSourceR page, mention SSH clone address 2022-09-16 14:04:24 +00:00
fr33domlover
40f741e504 UI: Fix and re-enable getRepoSourceR (repo content file/dir browsing) 2022-09-16 13:47:10 +00:00
fr33domlover
b66bab4295 UI: Fix and re-enable getRepoCommitsR (i.e. repo history view) 2022-09-16 12:46:52 +00:00
fr33domlover
91cdbf51ab UI: Fix and re-enable getRepoCommitR 2022-09-16 11:41:58 +00:00
fr33domlover
e78f043f49 C2S & UI: Allow creation of a new Repo 2022-09-16 10:34:44 +00:00
fr33domlover
8ec98e2a59 S2S: Invite->Accept->Grant (for Repo, Deck, Loom and Person, not for Group)
Person inbox handler:
    - Invite: Parse and insert to inbox
    - Grant: Parse and insert to inbox

Repo/Deck/Loom inbox handler:
    - Invite: Parse and remember as Collab record in DB for later
    - Accept: Send a Grant (and remember it in DB)

Along with inviteC and acceptC, the Invite->Accept->Grant flow is now fully
federated, yay!

What's missing is UI for actually using it. Coming soon.
2022-09-08 12:00:14 +00:00
fr33domlover
00a39475eb S2S: Prepare inbox handler for Group as well 2022-09-06 17:41:09 +00:00
fr33domlover
9dddc7d846 S2S: Prepare inbox handlers for Repo, Deck and Loom 2022-09-06 10:52:14 +00:00
fr33domlover
cdcf3a3326 Control.Applicative.Local: Rename parameter to avoid confusing name shadowing 2022-09-05 16:27:21 +00:00
fr33domlover
5a6ae76b76 Add missing signature to function in Vervis.RemoteActorStore
There are many more missing, but... just felt like fixing a warning :)
2022-09-05 16:25:59 +00:00
fr33domlover
ac867e56f2 S2S: Switch from Grant->Accept->Enable to Invite->Accept->Grant
Giving access now starts with an Invite activity, followed by Accept from the
Invite's recipient. Finally, the resource sends a Grant, which is the actual
OCap.
2022-09-05 16:19:52 +00:00
fr33domlover
0d96ee0775 DB: Add CollabTopicLocalReceive and CollabRecipLocalReceive tables
I was going to link the matching Accept tables to them, but then switched to
the Invite-Accept-Grant model and going to implement it in the next patches. So
I'm committing these new tables just in case I decide to revert to the current
model.
2022-09-01 17:44:43 +00:00
fr33domlover
4269385e15 DB: Add received::UTCTime field to InboxItem
To record *when* an activity, local or remote, was inserted into the specific
inbox. I'm surprised I haven't been keeping that data until now :P
2022-09-01 11:21:31 +00:00
fr33domlover
dd0bdaa742 S2S: Implement preparation and generic steps in person inbox post handler
The steps are:

- Parse activity ID and match with the authenticated sender
- For local activity (we got via forwarding), find in DB
- For remote activity, cache in DB
- Insert activity to recipient's inbox

What's not there yet is the actual logic of handling specific activities.
2022-08-31 13:01:04 +00:00
fr33domlover
b0576f9bf6 DB: Separate tables for CollabTopicLocalAccept and CollabTopicRemoteAccept
Previously there was just CollabTopicAccept, which worked only for local topics
but pretended to apply to both, due to directly pointing to Collab, thus
possible to insert rows even if there's a CollabTopicRemote.

The new situation is a new CollabTopicLocal table to which the local topic
things point, thus keeping the local and remote data separate and difficult to
confuse.
2022-08-30 08:28:44 +00:00
fr33domlover
9e6eb9bec6 Support delivery to Group followers collection 2022-08-29 21:41:13 +00:00
fr33domlover
b7eb7a17d2 C2S: Implement acceptC, allowing people to accept Grants given to them 2022-08-29 20:56:30 +00:00
fr33domlover
e8ed2d5f24 Remove accidental trailing space 2022-08-29 20:55:02 +00:00
fr33domlover
d741d0e918 C2S: grantC: Insert Collab records for Grants with remote topics too 2022-08-28 13:51:43 +00:00
fr33domlover
06c520f6aa C2S: Implement grantC and enable in person outbox handler 2022-08-22 16:59:22 +00:00
fr33domlover
158ad789ec C2S: In automatic Grant upon Deck creation, insert CollabTopicAccept record
Since that table being added, a Collab without a CollabTopicAccept is
considered an open proposal/invitation waiting for completion. So inserting the
CollabTopicAccept is now required for making the Grant valid and active.
2022-08-21 18:15:44 +00:00
fr33domlover
10645bf02b DB: Add Collab tables for recording Recip's and Topic's Accept activities 2022-08-21 18:10:03 +00:00
fr33domlover
0bd7568ca5 ActivityPub: Move 'fulfills' property from Grant type to Activity type 2022-08-16 14:55:21 +00:00
fr33domlover
26ec6527e2 Client, UI: Form for creating a new Deck 2022-08-16 13:17:26 +00:00
fr33domlover
a12409548f C2S: Enable creation of new decks, with automatic Grant and Follow 2022-08-15 20:21:10 +00:00
fr33domlover
87bb369120 ActivityPub: Add a PatchTracker actor type 2022-08-15 18:22:46 +00:00
fr33domlover
2e72684fd5 Switch to new actor layout
This is such a huge patch, it's probably impossible to tell what it does by
looking at the code. One thing is clear: It changes *everything* :P so here's
an overview:

- There are now 5 types of actors, each having its own top-level route
- So projects, repos, etc. are no longer "under" sharers
- Actor routes are now based on their KeyHashid, there are no "idents" anymore,
  i.e. URLs look random and don't contain user or repo names
- No sharers anymore; people and groups are distinct entities not sharing a
  common namespace or anything like that
- Project has been renamed to Deck and it simply means a ticket tracker; repos
  are no longer "under" projects
- In addition to Person, Group, Repo and Deck, there's a new actor type Loom,
  which is a patch tracker; i.e. Repo actors don't manage MRs anymore
- All C2S and S2S is temporarily disabled, because huge changes to the whole
  code are required and I'll do them gradually in the next patches
- Since form-based actions are implemented using C2S, they're disabled as well,
  so Vervis is now essentially read-only
- Some views have been temporarily removed, e.g. repo history and commit view
- A huge set of DB migrations has been added to adapt the DB to these changes;
  I haven't tested them yet on a read DB so there may be errors there; I'll fix
  them in the next patches if I find any (probably going to test on the main
  instance where Vervis itself is hosted...)
- Some modules got tech upgrades, e.g. LocalActor became a higher-kinded type
  and a similar pattern is probably relevant for several other types
- There's an 'Actor' entity in the DB schema now, and all 5 actor types use it
  for common things like inbox and outbox
- Although inbox and outbox are used only by Actor, so essentially could be
  removed, I haven't removed them; that's because I wonder if at some point
  users can have a tree of inboxes much like in email; I don't have an excuse
  for Outbox, but anyway, leaving them as is for now
- Workflows, roles and collaborators are partially removed/unused until I
  figure out a sane federated way to provide these features
- Since repo routes don't contain a "sharer" anymore, SSH URIs are now simpler,
  they already look like user@host/repo regardless of who "controls" that repo
2022-08-15 13:57:42 +00:00
fr33domlover
91b2d36a19 Move models and routes files from config/ to new th/ dir 2022-07-25 18:40:36 +00:00
fr33domlover
066285d3a3 Move robots.txt and favicon from config/ to new embed/ dir 2022-07-25 17:40:19 +00:00
fr33domlover
b3cd7ca28f C2S: Implement ticket tracker creation
* Publish a Create activity and respond with a Grant activity
* postProjectsR reuses that code
* No automatic following at the moment
* Workflow and role specified in new project form are ignored for now
* Can't create tracker under a group yet, just under the user
2022-07-25 17:15:22 +00:00
fr33domlover
3cda2205c5 Web.ActivityPub: Remove fake extContext, the URI doesn't work anymore anyway 2022-07-25 09:10:24 +00:00
fr33domlover
e2591734d3 Web.ActivityPub: Update representation of actor and project
Ugh, that module is such a horrible mess... I hope to turn it soon into
something sane. Is there some generic non-clumsy way restructure the AP
parser/encoder API?

For now, making these ugly changes to support the represenation of
Create {TicketTracker}, which I'm about to implement.
2022-07-24 16:52:28 +00:00
fr33domlover
88b8027572 DB: Move project inbox, outbox & followers into a new Actor table 2022-07-19 12:12:49 +00:00
fr33domlover
86b35e9b56 Style: Replace yesod favicon with Vervis icon made by ikomi (thanks <3) 2022-07-12 14:08:37 +00:00
fr33domlover
b18c0cb255 C2S: applyC: Implement the missing support for patching Git repos 2022-06-26 14:15:52 +00:00
fr33domlover
8186e64a26 S2S: repoApplyF: Implement the missing support for patching Git repos 2022-06-26 14:00:28 +00:00
fr33domlover
a6e4587281 Raise build-time error on incomplete patterns
I realized I never intend to leave patterns (e.g. pattern matching in a 'case'
clause) incomplete, i.e. some cases left missing. When I do that it means I
forgot, and I'd like GHC to highlight it by raising an error instead of just
warning. Vervis has lots of warnings so it's hard to detect among them.

I suppose in other kinds of software people sometimes leave incomplete patterns
intentionally / are okay with a runtime exception being thrown? In a web
application, I definitely want to handle all cases, and be in control of how
errors are handled and displayed in UI.
2022-06-26 13:54:37 +00:00
fr33domlover
842f27f515 C2S: Implement applyC, works only for Darcs right now 2022-06-25 19:59:26 +00:00
fr33domlover
61b9710e38 S2S: repoApplyF: Support local sharer-hosted proposals 2022-06-24 05:39:24 +00:00
fr33domlover
02734d02f2 S2S: repoApplyF: Support local repo-hosted proposals 2022-06-24 05:02:54 +00:00
fr33domlover
c3ff3c40eb S2S: repoApplyF, for now only on remotely hosted patches 2022-06-23 09:09:02 +00:00
fr33domlover
bc7806b100 In migration code, rename Apply to Run to avoid confusion with Apply activity 2022-06-22 07:45:35 +00:00
fr33domlover
1e759698c1 Web.ActivityPub: Add capability URI field to Activity type 2022-06-22 07:39:38 +00:00
fr33domlover
bfa9774f83 DB: Switch to more flexible collaborator model 2022-06-22 06:19:37 +00:00
fr33domlover
bf2e172f6e C2S: addBundleC for adding a new patch bundle version to a Ticket 2020-09-13 12:48:03 +00:00
fr33domlover
1b304994d0 S2S: Add 'Add' activity, adds a new version of the patch bundle to a Ticket 2020-09-10 10:57:02 +00:00
fr33domlover
e2ac053d2b No CSRF token check for Dvara routes, they do it for themselves when needed 2020-09-01 14:11:47 +00:00
fr33domlover
7415175bea Fix pattern matching missing case 2020-08-31 09:19:34 +00:00
fr33domlover
201736427e Client: Add form to submit a patch via Offer activity 2020-08-17 13:30:43 +00:00
fr33domlover
7812fa6e8f Client: Add form for submitting a patch to a repo 2020-08-17 13:01:29 +00:00
fr33domlover
32adee0a75 Don't accept Darcs MRs with more than one patch bundle file 2020-08-17 09:01:14 +00:00
fr33domlover
cb11ea6447 DB: Add media type field to 'Patch' entity
This patch (haha) also adds a VCS field to the AP representation of repos
2020-08-14 21:16:33 +00:00
fr33domlover
b16c9505af S2S & C2S: Switch from single-patch MR version to multi-patch bundle support 2020-08-13 10:26:20 +00:00
fr33domlover
da01fcf451 S2S: Fix bug: in *UndoF, when unresolving ticket, ticketStatus wasn't updated 2020-08-06 13:18:38 +00:00
fr33domlover
be3cf50283 C2S: Fix bug: undoC: When deleting TicketResolve, ticketStatus wasn't updated 2020-08-06 07:14:06 +00:00
fr33domlover
9f34106a87 Client: Add forms for resolving and unresolving a ticket/MR 2020-08-05 20:41:33 +00:00
fr33domlover
5a0c46ad5c GET ticket handlers: Provide 'resolvedBy', set to the Resolve activity's ID URI 2020-08-05 12:43:04 +00:00
fr33domlover
de5d24edca When grabbing ticket/patch from DB, grab the TicketResolve* record too 2020-08-05 11:04:00 +00:00
fr33domlover
7a74dcc55e Web.ActivityPub: Allow to specify 'resolved' and 'resolvedBy' for 'Ticket' 2020-08-05 10:11:16 +00:00
fr33domlover
9317e514b2 S2S unresolve, C2S resolve & unresolve, use C2S in the UI buttons 2020-08-05 08:28:58 +00:00
fr33domlover
7f106023b0 S2S: Implement inbox handlers for Resolve activity 2020-07-28 09:35:27 +00:00
fr33domlover
58c0719370 Web.ActivityPub: Add a Resolve activity 2020-07-23 14:27:11 +00:00
fr33domlover
1bd7995bb5 DB: Fix migration 173 for future instances to avoid the RemoteCollection bug 2020-07-23 13:38:46 +00:00
fr33domlover
ac9c79c761 DB: RemoteCollection was referring to itself accidentally, add migration to fix 2020-07-23 13:33:54 +00:00
fr33domlover
b050c9225d Web.ActivityPub: Add 'currentVersion' property to 'Patch' type 2020-07-23 10:47:35 +00:00
fr33domlover
c1f0722c21 C2S: createTicketC: Allow to submit MRs i.e. Ticket with a Patch attached 2020-07-22 13:00:48 +00:00
fr33domlover
fd8405e741 S2S: repoCreateTicketF: Store a Patch record in DB, to have a local copy 2020-07-21 10:03:51 +00:00
fr33domlover
029fce58a4 S2S: Repos now accept remotely hosted patches via Create/Ticket 2020-07-21 09:39:36 +00:00
fr33domlover
f286f35a87 S2S: Add repo patch support to checkCreateTicket 2020-07-19 12:48:39 +00:00
fr33domlover
f7c0807775 C2S: offerTicketC: Support offering a patch to a repo 2020-07-16 11:30:22 +00:00
fr33domlover
3e7e885300 S2S: Implement patch submission via repoOfferTicketF 2020-07-16 08:22:13 +00:00
fr33domlover
6d4d77255f S2S: Prepare Offer/Ticket parsing code for handling a remote patch/MR 2020-07-15 13:00:58 +00:00
fr33domlover
c78becaf5e S2S: projectCreateTicketF: Refactor to use new utils 2020-07-15 11:20:11 +00:00
fr33domlover
e46bcac559 S2S: sharerCreateTicketF: Tweak to use the new utils 2020-07-15 10:14:41 +00:00
fr33domlover
1a8ecb5995 S2S: Refactor projectOfferTicketF to use the new utils 2020-07-15 09:58:59 +00:00
fr33domlover
58e88d1e1b Upgrade sharerOfferTicketF to new utils 2020-07-15 08:00:08 +00:00
fr33domlover
75c0bc0939 Web.ActivityPub: Ticket attachment's Offer object can be either URI or a Patch
This will allow to use this representation for Offer and Create activities.
When creating a new MR, the inner Offer's 'object' is a 'Patch' object. When
serving an existing hosted MR, the inner Offer's 'object' is just a URI
pointing to the patch.
2020-07-14 11:25:37 +00:00
fr33domlover
6d80b1e4f1 Web.ActivityPub: In MR, the 'object' of the 'Offer' is a 'Patch' URI
Instead of an 'OrderedCollection' of the versions
2020-07-14 11:10:43 +00:00
fr33domlover
216aaa72ee Web.ActivityPub: Add PatchLocal type similar to TicketLocal 2020-07-14 09:56:13 +00:00
fr33domlover
fa3348513a For latest-version patches, provide a 'previousVersions' list 2020-07-14 08:50:57 +00:00
fr33domlover
a06d273107 C2S: Implement offerDepC, allowing to create ticket dependencies 2020-07-13 13:43:20 +00:00
fr33domlover
90086f1329 In audience parsing, provide version without bcc & list hosts for inbox fwding 2020-07-12 11:17:12 +00:00
fr33domlover
2a6bba89d5 C2S: Reimplement offerTicketC using the new tools 2020-07-07 07:26:51 +00:00
fr33domlover
511c3c60db C2S: In yesod authorization check, support OAuth2 as login method 2020-07-06 08:01:02 +00:00
fr33domlover
d392a37707 Rename InboxR to InboxDebugR, much clearer that way 2020-07-02 13:34:38 +00:00
fr33domlover
5d25aba239 C2S: Implement real C2S access via outbox POSTing and OAuth2 2020-07-02 13:21:59 +00:00
fr33domlover
a0325da028 S2S: Implement projectOfferDepF and repoOfferDepF 2020-06-22 11:29:30 +00:00
fr33domlover
5cf105fafb Move checkDepAndTarget from Vervis.Federation.Ticket to Vervis.Ticket
I'm moving it there because it's going to be used in C2S too, in offerDepC.
2020-06-21 12:31:11 +00:00
fr33domlover
4fc50f0870 Move hostIsLocal from Vervis.ActivityPub to Yesod.ActivityPub 2020-06-21 12:29:37 +00:00
fr33domlover
2cddadd679 sharerOfferDepF: If parent is remote and child is mine, record TicketDepOffer 2020-06-21 09:06:02 +00:00
fr33domlover
bc4248d7ca S2S: Handle remote dep in sharerAcceptF
If sharer receives Accept on an Offer/Dep where the sharer hosts the child
ticket, it records a RemoteTicketDependency and runs inbox forwarding to ticket
followers. But this relies on a TicketDependencyOffer record already existing.
I'll take care of that in the next patches.

sharerAcceptF and sharerRejectF now use the insertToInbox from
Vervis.Federation.Util instead of their own copies of it, which were identical
anyway. Perhaps gradually all the inbox insertion in all S2S handlers will
switch to using that function.
2020-06-21 08:02:05 +00:00
fr33domlover
a2468c52fd Prepare for ticket dependency federation
To be honest, this is a huge patch that changes tons of stuff and probably
should have been broken up into small changes. But I already had the codebase
not building, so... just did all of this at once :P

Basically this patch does the following:

- DB migrations for ticket dependency related tables, e.g. allowing a remote
  author and a remote child
- Allowing S2S handlers to provide an async continued processing function,
  which is executed and the result then added to the debug page
- Most UI and functionality related to ticket deps is disabled, new
  implementation being added gradually via ActivityPub
- Improvements to AP tools, e.g. allow to specify multiple hosts for approved
  forwarding when sending out an activity, and allow to specify audience of
  software-authored activities using a convenient human-friendly structure
- Implementation of S2S sharerOfferDepF which creates a dependency under a
  sharer-hosted ticket/patch and sends back an Accept
2020-06-18 10:38:04 +00:00
fr33domlover
854d35fd9b C2S: Support following a sharer-patch and repo-patch 2020-05-28 07:48:39 +00:00
fr33domlover
3fb529325d S2S: Support commenting on sharer-patch and repo-patch 2020-05-27 14:07:02 +00:00
fr33domlover
cf946e0326 S2S: Support unfollowing sharer-patch and repo-patch
- Sharer-patch was already working due to the shared DB tabled
- Repo-patch support added
- Fixed a bug in following project-tickets: It allowed to follow a
  sharer-ticket by sending the Follow to the project. Now, the project allows
  to follow only the project-tickets, and refuses to handle a sharer-ticket.
2020-05-27 11:59:53 +00:00
fr33domlover
c7b6ad643b S2S: Support following sharer-patch and repo-patch
Also fixed a bug in which trying to follow a ticket with nonexistent
ltkhid/talkhid would result with 404 as if the actor inbox is nonexistent. Now,
there's a friendly message reported.
2020-05-27 11:39:19 +00:00
fr33domlover
06a051d2e5 Support addressing, delivery and forwarding for sharer-patches and repo-patches 2020-05-27 10:38:28 +00:00
fr33domlover
d9c00cba1f Add repo-hosted patch routes and GET handlers 2020-05-26 14:51:11 +00:00
fr33domlover
e29233a59f Rename RepoPatchR to RepoCommitR, we'll use the old name for merge requests 2020-05-26 08:54:21 +00:00
fr33domlover
ad8c0ce8b4 Return sorted PatchId list from the get*Patch functions 2020-05-26 08:41:02 +00:00
fr33domlover
e68a659221 Support forwarding activities from repo actors 2020-05-25 13:36:34 +00:00
fr33domlover
17e59af1c4 AP: In getSharerPatchR, provide the list of patch versions, latest first 2020-05-25 12:39:25 +00:00
fr33domlover
c63479470e Add patch version route and GET handler, serving a specific patch file 2020-05-25 09:40:48 +00:00
fr33domlover
55c87b8a54 AP: Recognize "CryptographicKey" as a type of http sig keys
The examples in the security vocabulary's spec use "Key" but the JSON-LD
context doesn't define that term. From now on, just in case, recognizing both
"Key" and "CryptographicKey" as indication that the object is a key.

zPlus, thanks for finding this bug!
2020-05-25 09:37:15 +00:00
fr33domlover
417fcd3e94 S2S: If sharer inbox handler fails, return and log the error message 2020-05-24 13:53:31 +00:00
fr33domlover
d56a7411fc Refactor sharer-ticket and sharer-patch GET handler code to reuse similar parts 2020-05-24 13:31:58 +00:00
fr33domlover
02c42029d2 Add GET routes and handlers for sharer-hosted patches 2020-05-24 09:17:49 +00:00
fr33domlover
bb6785de75 DB: Generalize TicketProjectLocal into TicketContextLocal
This is the first step preparing for patches and merge requests.

The work-item aspect of MRs will reuse the Ticket related tables, except MRs
will live under repos. So, the context of tickets will no longer be just
projects, but will also be repos.

So, TicketProjectLocal turns into TicketContextLocal, and there are 2 new
tables that refer to it: TicketProjectLocal and TicketRepoLocal. Tickets will
have the former, MRs will have the latter.
2020-05-18 10:28:43 +00:00
fr33domlover
77e576ccb2 Startup: Sort the repo-tree-from-filesystem, it's not sorted by default 2020-05-14 12:33:51 +00:00
fr33domlover
2063c7313b Startup: If repo dir check fails, print both versions of repo tree 2020-05-14 12:11:31 +00:00
fr33domlover
cac4edc8eb getProjectTicketsR: In AS2, list remote tickets too 2020-05-14 11:13:04 +00:00
fr33domlover
d29ba23bfb In getProjectTicket, return TUP alongside TAL to prove it exists 2020-05-14 09:09:57 +00:00
fr33domlover
036c60171b In getSharerTicket, support remote project 2020-05-14 08:59:34 +00:00
fr33domlover
003adcbf7b Comment out more uses of ticket team collection 2020-05-14 08:58:37 +00:00
fr33domlover
a5348245f6 Comment out some usage of ticket team collection for addressing
Removed its usage in pseudo-client when publishing a comment, and removed it
from inbox forwarding when handling a remote comment.

Very possibly, the ticket team collection will be entirely removed. For now
leaving it there as-is. Just not using it for addressing in activities.
2020-05-13 14:00:38 +00:00
fr33domlover
a548dc8c5b S2S: sharerCreateNoteF: If ctx is sharer-ticket of another user, store to inbox 2020-05-13 13:49:22 +00:00
fr33domlover
f296dc173c C2S: In followC, return friendly message if already following the target object 2020-05-13 13:29:39 +00:00
fr33domlover
43cd1a95f3 S2S: sharerCreateNoteF caches note and does inbox fwd if sharer is ticket owner 2020-05-13 13:06:28 +00:00
fr33domlover
c91908941b S2S: sharerCreateNoteF & projectCreateNoteF can handle sharer-hosted tickets 2020-05-11 18:59:29 +00:00
fr33domlover
edaa3c49b2 C2S: Rewrite createNoteC based on createTicketC 2020-05-01 17:48:01 +00:00
fr33domlover
23056b3b3c DB: Attach a RemoteDiscussion to each RemoteTicket, for caching comments 2020-04-14 18:24:19 +00:00
fr33domlover
6c8b9664a2 When HTTP-fetching actors, remember their 'followers' as a LocalURI
The implementation felt quite weird, had to add an extra field to Fetched and
to VerifKeyDetail. Should probably figure out the whole mess in that code, have
something clean there. Easily add fields. Easily and safely re-fetch an actor
or key.
2020-04-11 14:58:38 +00:00
fr33domlover
7dc0ba2bf1 Fix error message for HTTP inbox forwarding 2020-04-11 14:03:54 +00:00
fr33domlover
04fc94cedb S2S: Write Create/Ticket project inbox handler: list ticket & do inbox fwding 2020-04-11 13:57:43 +00:00
fr33domlover
40a5b336a4 S2S: In Undo handler for sharer inbox, support unfollowing sharer tickets 2020-04-10 10:47:43 +00:00
fr33domlover
e406b08f44 S2S: In Follow handler for sharer inbox, support following of sharer tickets 2020-04-10 10:34:22 +00:00
fr33domlover
f4ab99f7bb C2S: In Follow handler, support following sharer-hosted tickets 2020-04-09 20:04:21 +00:00
fr33domlover
90bac5c34e Support sharer-hosted tickets in AP local dispatch and delivery 2020-04-09 17:39:36 +00:00
fr33domlover
ef4a8f4015 Write S2S Create/Ticket handler for sharer inbox 2020-04-09 12:21:17 +00:00
fr33domlover
f18c15f038 Rename the TicketR routes to ProjectTicketR for clarity
Now it's much clearer when looking at the code, that these routes are about
project-hosted tickets, and it's easier to see where the author-hosted
equivalents are missing.
2020-04-09 07:36:01 +00:00
fr33domlover
4a362632be Update S2S Accept handler to handle Accept on a Create/Ticket 2020-04-08 17:02:04 +00:00
fr33domlover
318f182245 Add OAuth2 subsite 2020-03-28 14:28:24 +00:00
fr33domlover
ac477ab739 Add OAuth2 tables to database, and run their migrations 2020-03-28 14:18:00 +00:00
fr33domlover
8f3ac50963 Verify TUP existence (when relevant) in all project-hosted ticket routes 2020-02-24 15:36:43 +00:00
fr33domlover
bf4a0e4c95 getTicketsR: Deduce ticket URL correctly for HTML output too 2020-02-23 15:41:08 +00:00
fr33domlover
ca0c7124c1 In C2S Offer{Ticket} on local project, insert a TicketUnderProject record 2020-02-23 15:38:22 +00:00
fr33domlover
f6903364f4 getTicketsR: Deduce ticket URLs correctly for JSON output 2020-02-23 13:22:32 +00:00
fr33domlover
a00c45a444 Implement C2S Create{Ticket}, available in PublishR and in postTicketsR
IMPORTANT: Since a lot of ticket code still doesn't use TicketUnderProject,
creating tickets now appears to be failing. Usage of this patch as is, is at
your own risk ^_^ the next patches will update the ticket handlers to fix this
problem.
2020-02-22 19:45:27 +00:00
fr33domlover
e0300ba0fa Write recipient filtering utility function 2020-02-19 10:59:38 +00:00
fr33domlover
a53fbcf1c0 Vervis.ActivityPub: Implement general-purpose full local delivery
Delivery of an activity into local inboxes is being done using custom local
functions. Each C2S or S2S handler has its own specific variant for this.

As part of the ongoing refactoring and evolution of the federation code, I
implemented a general-purpose local delivery function: It takes a
LocalRecipientSet and simply delivers to everyone, no handler-specific
assumptions or limitations.

To limit the recipient set according to handler specific rules, just
filter/adapt/edit it before passing to the delivery function.

The function isn't exported yet, but the existing 'deliverLocal' that delivers
only to actors and to author's followers is now implemented via the new
general-purpose function. I hope that's a step towards doing all the local
delivery using this one function, simplifying the complicated federation
code.
2020-02-18 13:34:34 +00:00
fr33domlover
adc107bb4c Web.ActivityPub: Add createTarget field
I'll use this for C2S to allow client to state who the tracker actor is. It's
still possible to do without it, by HTTP GETing the ticket's context and
checking whether we got an actor, or a non-actor with ticketsTrackedBy. Tbh I'm
adding createTarget simply because it's easier for coding, no need for a custom
variant of actor fetching :P
2020-02-18 13:26:28 +00:00
fr33domlover
257a811a8b Remove some unused imports from Vervis.Foundation 2020-02-18 13:25:26 +00:00
fr33domlover
1a650a783f Web.ActivityPub: Move ticketContext from TicketLocal to Ticket
This allows the context to be specified even when replies/followers/deps/etc.
aren't. This is needed for Create-ing a Ticket. Also, it allows a ticket's
context to be on a different host than where it's hosted, which is also needed
for the Create flow.
2020-02-11 14:14:52 +00:00
fr33domlover
6d25d7ec2c Web.ActivityPub: Allow Create object to be a Ticket 2020-02-10 14:51:32 +00:00
fr33domlover
0de98a9cdd Implement sharer ticket JSON view, including discussion, followers, deps etc. 2020-02-10 14:10:01 +00:00
fr33domlover
00e0f7c14f DB: Switch RemoteMessage to use RemoteObject 2020-02-10 14:07:00 +00:00