Add group, WIP on role (#17)
This commit is contained in:
@@ -84,6 +84,14 @@ module Json =
|
|||||||
override _.ReadJson(reader: JsonReader, _: Type, _: OpenGraphType, _: bool, _: JsonSerializer) =
|
override _.ReadJson(reader: JsonReader, _: Type, _: OpenGraphType, _: bool, _: JsonSerializer) =
|
||||||
(string >> OpenGraphType.Parse) reader.Value
|
(string >> OpenGraphType.Parse) reader.Value
|
||||||
|
|
||||||
|
/// <summary>Converter for the <see cref="PageId" /> type</summary>
|
||||||
|
type PageIdConverter() =
|
||||||
|
inherit JsonConverter<PageId>()
|
||||||
|
override _.WriteJson(writer: JsonWriter, value: PageId, _: JsonSerializer) =
|
||||||
|
writer.WriteValue(string value)
|
||||||
|
override _.ReadJson(reader: JsonReader, _: Type, _: PageId, _: bool, _: JsonSerializer) =
|
||||||
|
(string >> PageId) reader.Value
|
||||||
|
|
||||||
/// <summary>Converter for the <see cref="Permalink" /> type</summary>
|
/// <summary>Converter for the <see cref="Permalink" /> type</summary>
|
||||||
type PermalinkConverter() =
|
type PermalinkConverter() =
|
||||||
inherit JsonConverter<Permalink>()
|
inherit JsonConverter<Permalink>()
|
||||||
@@ -92,13 +100,21 @@ module Json =
|
|||||||
override _.ReadJson(reader: JsonReader, _: Type, _: Permalink, _: bool, _: JsonSerializer) =
|
override _.ReadJson(reader: JsonReader, _: Type, _: Permalink, _: bool, _: JsonSerializer) =
|
||||||
(string >> Permalink) reader.Value
|
(string >> Permalink) reader.Value
|
||||||
|
|
||||||
/// <summary>Converter for the <see cref="PageId" /> type</summary>
|
/// <summary>Converter for the <see cref="PersonGroup" /> type</summary>
|
||||||
type PageIdConverter() =
|
type PersonGroupConverter() =
|
||||||
inherit JsonConverter<PageId>()
|
inherit JsonConverter<PersonGroup>()
|
||||||
override _.WriteJson(writer: JsonWriter, value: PageId, _: JsonSerializer) =
|
override _.WriteJson(writer: JsonWriter, value: PersonGroup, _: JsonSerializer) =
|
||||||
writer.WriteValue(string value)
|
writer.WriteValue(string value)
|
||||||
override _.ReadJson(reader: JsonReader, _: Type, _: PageId, _: bool, _: JsonSerializer) =
|
override _.ReadJson(reader: JsonReader, _: Type, _: PersonGroup, _: bool, _: JsonSerializer) =
|
||||||
(string >> PageId) reader.Value
|
(string >> PersonGroup.Parse) reader.Value
|
||||||
|
|
||||||
|
/// <summary>Converter for the <see cref="PersonRole" /> type</summary>
|
||||||
|
type PersonRoleConverter() =
|
||||||
|
inherit JsonConverter<PersonRole>()
|
||||||
|
override _.WriteJson(writer: JsonWriter, value: PersonRole, _: JsonSerializer) =
|
||||||
|
writer.WriteValue(string value)
|
||||||
|
override _.ReadJson(reader: JsonReader, _: Type, _: PersonRole, _: bool, _: JsonSerializer) =
|
||||||
|
(string >> PersonRole.Parse) reader.Value
|
||||||
|
|
||||||
/// <summary>Converter for the <see cref="PodcastMedium" /> type</summary>
|
/// <summary>Converter for the <see cref="PodcastMedium" /> type</summary>
|
||||||
type PodcastMediumConverter() =
|
type PodcastMediumConverter() =
|
||||||
@@ -180,8 +196,10 @@ module Json =
|
|||||||
ExplicitRatingConverter()
|
ExplicitRatingConverter()
|
||||||
MarkupTextConverter()
|
MarkupTextConverter()
|
||||||
OpenGraphTypeConverter()
|
OpenGraphTypeConverter()
|
||||||
PermalinkConverter()
|
|
||||||
PageIdConverter()
|
PageIdConverter()
|
||||||
|
PermalinkConverter()
|
||||||
|
PersonGroupConverter()
|
||||||
|
PersonRoleConverter()
|
||||||
PodcastMediumConverter()
|
PodcastMediumConverter()
|
||||||
PostIdConverter()
|
PostIdConverter()
|
||||||
TagMapIdConverter()
|
TagMapIdConverter()
|
||||||
|
|||||||
@@ -457,7 +457,7 @@ type WebLogUser = {
|
|||||||
PreferredName = ""
|
PreferredName = ""
|
||||||
PasswordHash = ""
|
PasswordHash = ""
|
||||||
Url = None
|
Url = None
|
||||||
AccessLevel = Author
|
AccessLevel = ContentAuthor
|
||||||
CreatedOn = Noda.epoch
|
CreatedOn = Noda.epoch
|
||||||
LastSeenOn = None }
|
LastSeenOn = None }
|
||||||
|
|
||||||
|
|||||||
@@ -61,18 +61,22 @@ module Noda =
|
|||||||
/// <summary>A user's access level</summary>
|
/// <summary>A user's access level</summary>
|
||||||
[<Struct>]
|
[<Struct>]
|
||||||
type AccessLevel =
|
type AccessLevel =
|
||||||
|
|
||||||
/// <summary>The user may create and publish posts and edit the ones they have created</summary>
|
/// <summary>The user may create and publish posts and edit the ones they have created</summary>
|
||||||
| Author
|
| ContentAuthor
|
||||||
|
|
||||||
/// <summary>The user may edit posts they did not create, but may not delete them</summary>
|
/// <summary>The user may edit posts they did not create, but may not delete them</summary>
|
||||||
| Editor
|
| Editor
|
||||||
|
|
||||||
/// <summary>The user may delete posts and configure web log settings</summary>
|
/// <summary>The user may delete posts and configure web log settings</summary>
|
||||||
| WebLogAdmin
|
| WebLogAdmin
|
||||||
|
|
||||||
/// <summary>The user may manage themes (which affects all web logs for an installation)</summary>
|
/// <summary>The user may manage themes (which affects all web logs for an installation)</summary>
|
||||||
| Administrator
|
| Administrator
|
||||||
|
|
||||||
/// <summary>Weights applied to each access level</summary>
|
/// <summary>Weights applied to each access level</summary>
|
||||||
static member private Weights =
|
static member private Weights =
|
||||||
[ Author, 10
|
[ ContentAuthor, 10
|
||||||
Editor, 20
|
Editor, 20
|
||||||
WebLogAdmin, 30
|
WebLogAdmin, 30
|
||||||
Administrator, 40 ]
|
Administrator, 40 ]
|
||||||
@@ -84,7 +88,7 @@ type AccessLevel =
|
|||||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||||
static member Parse level =
|
static member Parse level =
|
||||||
match level with
|
match level with
|
||||||
| "Author" -> Author
|
| "Author" -> ContentAuthor
|
||||||
| "Editor" -> Editor
|
| "Editor" -> Editor
|
||||||
| "WebLogAdmin" -> WebLogAdmin
|
| "WebLogAdmin" -> WebLogAdmin
|
||||||
| "Administrator" -> Administrator
|
| "Administrator" -> Administrator
|
||||||
@@ -93,7 +97,7 @@ type AccessLevel =
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
override this.ToString() =
|
override this.ToString() =
|
||||||
match this with
|
match this with
|
||||||
| Author -> "Author"
|
| ContentAuthor -> "Author"
|
||||||
| Editor -> "Editor"
|
| Editor -> "Editor"
|
||||||
| WebLogAdmin -> "WebLogAdmin"
|
| WebLogAdmin -> "WebLogAdmin"
|
||||||
| Administrator -> "Administrator"
|
| Administrator -> "Administrator"
|
||||||
@@ -269,6 +273,331 @@ type Chapter = {
|
|||||||
EndTime = None
|
EndTime = None
|
||||||
Location = None }
|
Location = None }
|
||||||
|
|
||||||
|
/// <summary>A group to which a podcast person can belong</summary>
|
||||||
|
type PersonGroup =
|
||||||
|
| Administration
|
||||||
|
| AudioPostProduction
|
||||||
|
| AudioProduction
|
||||||
|
| Cast
|
||||||
|
| Community
|
||||||
|
| CreativeDirection
|
||||||
|
| Misc
|
||||||
|
| VideoPostProduction
|
||||||
|
| VideoProduction
|
||||||
|
| Visuals
|
||||||
|
| Writing
|
||||||
|
|
||||||
|
/// <summary>Parse a string into a group</summary>
|
||||||
|
/// <param name="group">The string representation of the group</param>
|
||||||
|
/// <returns>The <c>PersonGroup</c> instance parsed from the string</returns>
|
||||||
|
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||||
|
static member Parse group =
|
||||||
|
match group with
|
||||||
|
| "Administration" -> Administration
|
||||||
|
| "Audio Post-Production" -> AudioPostProduction
|
||||||
|
| "Audio Production" -> AudioProduction
|
||||||
|
| "Cast" -> Cast
|
||||||
|
| "Community" -> Community
|
||||||
|
| "Creative Direction" -> CreativeDirection
|
||||||
|
| "Misc." -> Misc
|
||||||
|
| "Video Post-Production" -> VideoPostProduction
|
||||||
|
| "Video Production" -> VideoProduction
|
||||||
|
| "Visuals" -> Visuals
|
||||||
|
| "Writing" -> Writing
|
||||||
|
| _ -> invalidArg (nameof group) $"{group} is not a valid group"
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
override this.ToString() =
|
||||||
|
match this with
|
||||||
|
| Administration -> "Administration"
|
||||||
|
| AudioPostProduction -> "Audio Post-Production"
|
||||||
|
| AudioProduction -> "Audio Production"
|
||||||
|
| Cast -> "Cast"
|
||||||
|
| Community -> "Community"
|
||||||
|
| CreativeDirection -> "Creative Direction"
|
||||||
|
| Misc -> "Misc."
|
||||||
|
| VideoPostProduction -> "Video Post-Production"
|
||||||
|
| VideoProduction -> "Video Production"
|
||||||
|
| Visuals -> "Visuals"
|
||||||
|
| Writing -> "Writing"
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>The role a person plays for a podcast or a podcast episode</summary>
|
||||||
|
type PersonRole =
|
||||||
|
| Announcer
|
||||||
|
| AssistantCamera
|
||||||
|
| AssistantDirector
|
||||||
|
| AssistantEditor
|
||||||
|
| AssociateProducer
|
||||||
|
| AudioEditor
|
||||||
|
| AudioEngineer
|
||||||
|
| Author
|
||||||
|
| BookingCoordinator
|
||||||
|
| CameraGrip
|
||||||
|
| CameraOperator
|
||||||
|
| CoHost
|
||||||
|
| Composer
|
||||||
|
| Consultant
|
||||||
|
| ContentManager
|
||||||
|
| CoverArtDesigner
|
||||||
|
| CoWriter
|
||||||
|
| CreativeDirector
|
||||||
|
| DevelopmentProducer
|
||||||
|
| Director
|
||||||
|
| EditorialDirector
|
||||||
|
| ExecutiveProducer
|
||||||
|
| FactChecker
|
||||||
|
| FoleyArtist
|
||||||
|
| GraphicDesigner
|
||||||
|
| Guest
|
||||||
|
| GuestHost
|
||||||
|
| GuestWriter
|
||||||
|
| Host
|
||||||
|
| Intern
|
||||||
|
| LightingDesigner
|
||||||
|
| Logger
|
||||||
|
| ManagingEditor
|
||||||
|
| MarketingManager
|
||||||
|
| MusicContributor
|
||||||
|
| MusicProduction
|
||||||
|
| Narrator
|
||||||
|
| PostProductionEngineer
|
||||||
|
| Producer
|
||||||
|
| ProductionAssistant
|
||||||
|
| ProductionCoordinator
|
||||||
|
| RemoteRecordingEngineer
|
||||||
|
| Reporter
|
||||||
|
| Researcher
|
||||||
|
| SalesManager
|
||||||
|
| SalesRepresentative
|
||||||
|
| ScriptCoordinator
|
||||||
|
| ScriptEditor
|
||||||
|
| SeniorProducer
|
||||||
|
| SocialMediaManager
|
||||||
|
| Songwriter
|
||||||
|
| SoundDesigner
|
||||||
|
| StoryEditor
|
||||||
|
| StudioCoordinator
|
||||||
|
| TechnicalDirector
|
||||||
|
| TechnicalManager
|
||||||
|
| ThemeMusic
|
||||||
|
| Transcriber
|
||||||
|
| Translator
|
||||||
|
| VideoEditor
|
||||||
|
| VoiceActor
|
||||||
|
| Writer
|
||||||
|
| WritingEditor
|
||||||
|
|
||||||
|
/// <summary>Parse a string into a role</summary>
|
||||||
|
/// <param name="role">The string representation of the role</param>
|
||||||
|
/// <returns>The <c>PersonRole</c> instance parsed from the string</returns>
|
||||||
|
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||||
|
static member Parse role =
|
||||||
|
match role with
|
||||||
|
| "Announcer" -> Announcer
|
||||||
|
| "Assistant Camera" -> AssistantCamera
|
||||||
|
| "Assistant Director" -> AssistantDirector
|
||||||
|
| "Assistant Editor" -> AssistantEditor
|
||||||
|
| "Associate Producer" -> AssociateProducer
|
||||||
|
| "Audio Editor" -> AudioEditor
|
||||||
|
| "Audio Engineer" -> AudioEngineer
|
||||||
|
| "Author" -> Author
|
||||||
|
| "Booking Coordinator" -> BookingCoordinator
|
||||||
|
| "Camera Grip" -> CameraGrip
|
||||||
|
| "Camera Operator" -> CameraOperator
|
||||||
|
| "Co-Host" -> CoHost
|
||||||
|
| "Composer" -> Composer
|
||||||
|
| "Consultant" -> Consultant
|
||||||
|
| "Content Manager" -> ContentManager
|
||||||
|
| "Cover Art Designer" -> CoverArtDesigner
|
||||||
|
| "Co-Writer" -> CoWriter
|
||||||
|
| "Creative Director" -> CreativeDirector
|
||||||
|
| "Development Producer" -> DevelopmentProducer
|
||||||
|
| "Director" -> Director
|
||||||
|
| "Editorial Director" -> EditorialDirector
|
||||||
|
| "Executive Producer" -> ExecutiveProducer
|
||||||
|
| "Fact Checker" -> FactChecker
|
||||||
|
| "Foley Artist" -> FoleyArtist
|
||||||
|
| "Graphic Designer" -> GraphicDesigner
|
||||||
|
| "Guest" -> Guest
|
||||||
|
| "Guest Host" -> GuestHost
|
||||||
|
| "Guest Writer" -> GuestWriter
|
||||||
|
| "Host" -> Host
|
||||||
|
| "Intern" -> Intern
|
||||||
|
| "Lighting Designer" -> LightingDesigner
|
||||||
|
| "Logger" -> Logger
|
||||||
|
| "Managing Editor" -> ManagingEditor
|
||||||
|
| "Marketing Manager" -> MarketingManager
|
||||||
|
| "Music Contributor" -> MusicContributor
|
||||||
|
| "Music Production" -> MusicProduction
|
||||||
|
| "Narrator" -> Narrator
|
||||||
|
| "Post Production Engineer" -> PostProductionEngineer
|
||||||
|
| "Producer" -> Producer
|
||||||
|
| "Production Assistant" -> ProductionAssistant
|
||||||
|
| "Production Coordinator" -> ProductionCoordinator
|
||||||
|
| "Remote Recording Engineer" -> RemoteRecordingEngineer
|
||||||
|
| "Reporter" -> Reporter
|
||||||
|
| "Researcher" -> Researcher
|
||||||
|
| "Sales Manager" -> SalesManager
|
||||||
|
| "Sales Representative" -> SalesRepresentative
|
||||||
|
| "Script Coordinator" -> ScriptCoordinator
|
||||||
|
| "Script Editor" -> ScriptEditor
|
||||||
|
| "Senior Producer" -> SeniorProducer
|
||||||
|
| "Social Media Manager" -> SocialMediaManager
|
||||||
|
| "Songwriter" -> Songwriter
|
||||||
|
| "Sound Designer" -> SoundDesigner
|
||||||
|
| "Story Editor" -> StoryEditor
|
||||||
|
| "Studio Coordinator" -> StudioCoordinator
|
||||||
|
| "Technical Director" -> TechnicalDirector
|
||||||
|
| "Technical Manager" -> TechnicalManager
|
||||||
|
| "Theme Music" -> ThemeMusic
|
||||||
|
| "Transcriber" -> Transcriber
|
||||||
|
| "Translator" -> Translator
|
||||||
|
| "Editor (Video)" -> VideoEditor
|
||||||
|
| "Voice Actor" -> VoiceActor
|
||||||
|
| "Writer" -> Writer
|
||||||
|
| "Editor (Writing)" -> WritingEditor
|
||||||
|
| _ -> invalidArg (nameof role) $"{role} is not a valid role"
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
override this.ToString() =
|
||||||
|
match this with
|
||||||
|
| Announcer -> "Announcer"
|
||||||
|
| AssistantCamera -> "Assistant Camera"
|
||||||
|
| AssistantDirector -> "Assistant Director"
|
||||||
|
| AssistantEditor -> "Assistant Editor"
|
||||||
|
| AssociateProducer -> "Associate Producer"
|
||||||
|
| AudioEditor -> "Audio Editor"
|
||||||
|
| AudioEngineer -> "Audio Engineer"
|
||||||
|
| Author -> "Author"
|
||||||
|
| BookingCoordinator -> "Booking Coordinator"
|
||||||
|
| CameraGrip -> "Camera Grip"
|
||||||
|
| CameraOperator -> "Camera Operator"
|
||||||
|
| CoHost -> "Co-Host"
|
||||||
|
| Composer -> "Composer"
|
||||||
|
| Consultant -> "Consultant"
|
||||||
|
| ContentManager -> "Content Manager"
|
||||||
|
| CoverArtDesigner -> "Cover Art Designer"
|
||||||
|
| CoWriter -> "Co-Writer"
|
||||||
|
| CreativeDirector -> "Creative Director"
|
||||||
|
| DevelopmentProducer -> "Development Producer"
|
||||||
|
| Director -> "Director"
|
||||||
|
| EditorialDirector -> "Editorial Director"
|
||||||
|
| ExecutiveProducer -> "Executive Producer"
|
||||||
|
| FactChecker -> "Fact Checker"
|
||||||
|
| FoleyArtist -> "Foley Artist"
|
||||||
|
| GraphicDesigner -> "Graphic Designer"
|
||||||
|
| Guest -> "Guest"
|
||||||
|
| GuestHost -> "Guest Host"
|
||||||
|
| GuestWriter -> "Guest Writer"
|
||||||
|
| Host -> "Host"
|
||||||
|
| Intern -> "Intern"
|
||||||
|
| LightingDesigner -> "Lighting Designer"
|
||||||
|
| Logger -> "Logger"
|
||||||
|
| ManagingEditor -> "Managing Editor"
|
||||||
|
| MarketingManager -> "Marketing Manager"
|
||||||
|
| MusicContributor -> "Music Contributor"
|
||||||
|
| MusicProduction -> "Music Production"
|
||||||
|
| Narrator -> "Narrator"
|
||||||
|
| PostProductionEngineer -> "Post Production Engineer"
|
||||||
|
| Producer -> "Producer"
|
||||||
|
| ProductionAssistant -> "Production Assistant"
|
||||||
|
| ProductionCoordinator -> "Production Coordinator"
|
||||||
|
| RemoteRecordingEngineer -> "Remote Recording Engineer"
|
||||||
|
| Reporter -> "Reporter"
|
||||||
|
| Researcher -> "Researcher"
|
||||||
|
| SalesManager -> "Sales Manager"
|
||||||
|
| SalesRepresentative -> "Sales Representative"
|
||||||
|
| ScriptCoordinator -> "Script Coordinator"
|
||||||
|
| ScriptEditor -> "Script Editor"
|
||||||
|
| SeniorProducer -> "Senior Producer"
|
||||||
|
| SocialMediaManager -> "Social Media Manager"
|
||||||
|
| Songwriter -> "Songwriter"
|
||||||
|
| SoundDesigner -> "Sound Designer"
|
||||||
|
| StoryEditor -> "Story Editor"
|
||||||
|
| StudioCoordinator -> "Studio Coordinator"
|
||||||
|
| TechnicalDirector -> "Technical Director"
|
||||||
|
| TechnicalManager -> "Technical Manager"
|
||||||
|
| ThemeMusic -> "Theme Music"
|
||||||
|
| Transcriber -> "Transcriber"
|
||||||
|
| Translator -> "Translator"
|
||||||
|
| VideoEditor -> "Editor (Video)"
|
||||||
|
| VoiceActor -> "Voice Actor"
|
||||||
|
| Writer -> "Writer"
|
||||||
|
| WritingEditor -> "Editor (Writing)"
|
||||||
|
|
||||||
|
/// <summary>Get the display name of the role</summary>
|
||||||
|
/// <remarks>Both Video Production and Writing have an "Editor"; this is how it should be rendered in RSS feeds and
|
||||||
|
/// in the UI</remarks>
|
||||||
|
member this.ToDisplay() =
|
||||||
|
match this with VideoEditor | WritingEditor -> "Editor" | _ -> string this
|
||||||
|
|
||||||
|
/// <summary>Role / group cross-reference</summary>
|
||||||
|
static member GroupXref =
|
||||||
|
[ Announcer, Cast
|
||||||
|
AssistantCamera, VideoProduction
|
||||||
|
AssistantDirector, CreativeDirection
|
||||||
|
AssistantEditor, VideoPostProduction
|
||||||
|
AssociateProducer, CreativeDirection
|
||||||
|
AudioEditor, AudioPostProduction
|
||||||
|
AudioEngineer, AudioProduction
|
||||||
|
Author, Writing
|
||||||
|
BookingCoordinator, Administration
|
||||||
|
CameraGrip, VideoProduction
|
||||||
|
CameraOperator, VideoProduction
|
||||||
|
CoHost, Cast
|
||||||
|
Composer, AudioPostProduction
|
||||||
|
ContentManager, Administration
|
||||||
|
Consultant, Misc
|
||||||
|
CoverArtDesigner, Visuals
|
||||||
|
CoWriter, Writing
|
||||||
|
CreativeDirector, CreativeDirection
|
||||||
|
DevelopmentProducer, CreativeDirection
|
||||||
|
Director, CreativeDirection
|
||||||
|
EditorialDirector, Writing
|
||||||
|
ExecutiveProducer, CreativeDirection
|
||||||
|
FactChecker, Writing
|
||||||
|
FoleyArtist, AudioPostProduction
|
||||||
|
GraphicDesigner, Visuals
|
||||||
|
Guest, Cast
|
||||||
|
GuestHost, Cast
|
||||||
|
GuestWriter, Writing
|
||||||
|
Host, Cast
|
||||||
|
Intern, Misc
|
||||||
|
LightingDesigner, VideoProduction
|
||||||
|
Logger, Writing
|
||||||
|
ManagingEditor, Writing
|
||||||
|
MarketingManager, Administration
|
||||||
|
MusicContributor, AudioPostProduction
|
||||||
|
MusicProduction, AudioPostProduction
|
||||||
|
Narrator, Cast
|
||||||
|
PostProductionEngineer, AudioProduction
|
||||||
|
Producer, CreativeDirection
|
||||||
|
ProductionAssistant, Administration
|
||||||
|
ProductionCoordinator, Administration
|
||||||
|
RemoteRecordingEngineer, AudioProduction
|
||||||
|
Reporter, Cast
|
||||||
|
Researcher, Writing
|
||||||
|
SalesManager, Administration
|
||||||
|
SalesRepresentative, Administration
|
||||||
|
ScriptCoordinator, Writing
|
||||||
|
ScriptEditor, Writing
|
||||||
|
SeniorProducer, CreativeDirection
|
||||||
|
SocialMediaManager, Community
|
||||||
|
Songwriter, Writing
|
||||||
|
SoundDesigner, AudioPostProduction
|
||||||
|
StoryEditor, Writing
|
||||||
|
StudioCoordinator, AudioProduction
|
||||||
|
TechnicalDirector, AudioProduction
|
||||||
|
TechnicalManager, AudioProduction
|
||||||
|
ThemeMusic, AudioPostProduction
|
||||||
|
Transcriber, Writing
|
||||||
|
Translator, Writing
|
||||||
|
VideoEditor, VideoPostProduction
|
||||||
|
VoiceActor, Cast
|
||||||
|
Writer, Writing
|
||||||
|
WritingEditor, Writing ]
|
||||||
|
|
||||||
|
|
||||||
open NodaTime.Text
|
open NodaTime.Text
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,20 @@ let openGraphTypeConverterTests = testList "OpenGraphTypeConverter" [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/// Unit tests for the PageIdConverter type
|
||||||
|
let pageIdConverterTests = testList "PageIdConverter" [
|
||||||
|
let opts = JsonSerializerSettings()
|
||||||
|
opts.Converters.Add(PageIdConverter())
|
||||||
|
test "succeeds when serializing" {
|
||||||
|
let after = JsonConvert.SerializeObject(PageId "test-page", opts)
|
||||||
|
Expect.equal after "\"test-page\"" "Page ID serialized incorrectly"
|
||||||
|
}
|
||||||
|
test "succeeds when deserializing" {
|
||||||
|
let after = JsonConvert.DeserializeObject<PageId>("\"page-test\"", opts)
|
||||||
|
Expect.equal after (PageId "page-test") "Page ID deserialized incorrectly"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
/// Unit tests for the PermalinkConverter type
|
/// Unit tests for the PermalinkConverter type
|
||||||
let permalinkConverterTests = testList "PermalinkConverter" [
|
let permalinkConverterTests = testList "PermalinkConverter" [
|
||||||
let opts = JsonSerializerSettings()
|
let opts = JsonSerializerSettings()
|
||||||
@@ -150,17 +164,31 @@ let permalinkConverterTests = testList "PermalinkConverter" [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
/// Unit tests for the PageIdConverter type
|
/// Unit tests for the PersonGroupConverter type
|
||||||
let pageIdConverterTests = testList "PageIdConverter" [
|
let personGroupConverterTests = testList "PersonGroupConverter" [
|
||||||
let opts = JsonSerializerSettings()
|
let opts = JsonSerializerSettings()
|
||||||
opts.Converters.Add(PageIdConverter())
|
opts.Converters.Add(PersonGroupConverter())
|
||||||
test "succeeds when serializing" {
|
test "succeeds when serializing" {
|
||||||
let after = JsonConvert.SerializeObject(PageId "test-page", opts)
|
let after = JsonConvert.SerializeObject(Visuals, opts)
|
||||||
Expect.equal after "\"test-page\"" "Page ID serialized incorrectly"
|
Expect.equal after "\"Visuals\"" "PersonGroup serialized incorrectly"
|
||||||
}
|
}
|
||||||
test "succeeds when deserializing" {
|
test "succeeds when deserializing" {
|
||||||
let after = JsonConvert.DeserializeObject<PageId>("\"page-test\"", opts)
|
let after = JsonConvert.DeserializeObject<PersonGroup>("\"Cast\"", opts)
|
||||||
Expect.equal after (PageId "page-test") "Page ID deserialized incorrectly"
|
Expect.equal after Cast "PersonGroup deserialized incorrectly"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
/// Unit tests for the PersonRoleConverter type
|
||||||
|
let personRoleConverterTests = testList "PersonRoleConverter" [
|
||||||
|
let opts = JsonSerializerSettings()
|
||||||
|
opts.Converters.Add(PersonRoleConverter())
|
||||||
|
test "succeeds when serializing" {
|
||||||
|
let after = JsonConvert.SerializeObject(Host, opts)
|
||||||
|
Expect.equal after "\"Host\"" "PersonRole serialized incorrectly"
|
||||||
|
}
|
||||||
|
test "succeeds when deserializing" {
|
||||||
|
let after = JsonConvert.DeserializeObject<PersonRole>("\"Co-Host\"", opts)
|
||||||
|
Expect.equal after CoHost "PersonRole deserialized incorrectly"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -291,8 +319,10 @@ let configureTests = test "Json.configure succeeds" {
|
|||||||
Expect.hasCountOf ser.Converters 1u (has typeof<ExplicitRatingConverter>) "Explicit rating converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<ExplicitRatingConverter>) "Explicit rating converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<MarkupTextConverter>) "Markup text converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<MarkupTextConverter>) "Markup text converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<OpenGraphTypeConverter>) "OpenGraph type converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<OpenGraphTypeConverter>) "OpenGraph type converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<PermalinkConverter>) "Permalink converter not found"
|
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<PageIdConverter>) "Page ID converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<PageIdConverter>) "Page ID converter not found"
|
||||||
|
Expect.hasCountOf ser.Converters 1u (has typeof<PermalinkConverter>) "Permalink converter not found"
|
||||||
|
Expect.hasCountOf ser.Converters 1u (has typeof<PersonGroupConverter>) "PersonGroup converter not found"
|
||||||
|
Expect.hasCountOf ser.Converters 1u (has typeof<PersonRoleConverter>) "PersonRole converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<PodcastMediumConverter>) "Podcast medium converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<PodcastMediumConverter>) "Podcast medium converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<PostIdConverter>) "Post ID converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<PostIdConverter>) "Post ID converter not found"
|
||||||
Expect.hasCountOf ser.Converters 1u (has typeof<TagMapIdConverter>) "Tag map ID converter not found"
|
Expect.hasCountOf ser.Converters 1u (has typeof<TagMapIdConverter>) "Tag map ID converter not found"
|
||||||
@@ -318,8 +348,10 @@ let all = testList "Converters" [
|
|||||||
explicitRatingConverterTests
|
explicitRatingConverterTests
|
||||||
markupTextConverterTests
|
markupTextConverterTests
|
||||||
openGraphTypeConverterTests
|
openGraphTypeConverterTests
|
||||||
permalinkConverterTests
|
|
||||||
pageIdConverterTests
|
pageIdConverterTests
|
||||||
|
permalinkConverterTests
|
||||||
|
personGroupConverterTests
|
||||||
|
personRoleConverterTests
|
||||||
podcastMediumConverterTests
|
podcastMediumConverterTests
|
||||||
postIdConverterTests
|
postIdConverterTests
|
||||||
tagMapIdConverterTests
|
tagMapIdConverterTests
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ let ``Add succeeds`` (data: IData) = task {
|
|||||||
PreferredName = "n00b"
|
PreferredName = "n00b"
|
||||||
PasswordHash = "hashed-password"
|
PasswordHash = "hashed-password"
|
||||||
Url = Some "https://example.com/~new"
|
Url = Some "https://example.com/~new"
|
||||||
AccessLevel = Author
|
AccessLevel = ContentAuthor
|
||||||
CreatedOn = Noda.epoch + Duration.FromDays 365
|
CreatedOn = Noda.epoch + Duration.FromDays 365
|
||||||
LastSeenOn = None }
|
LastSeenOn = None }
|
||||||
let! user = data.WebLogUser.FindById newId rootId
|
let! user = data.WebLogUser.FindById newId rootId
|
||||||
@@ -47,7 +47,7 @@ let ``Add succeeds`` (data: IData) = task {
|
|||||||
Expect.equal it.PreferredName "n00b" "Preferred name is incorrect"
|
Expect.equal it.PreferredName "n00b" "Preferred name is incorrect"
|
||||||
Expect.equal it.PasswordHash "hashed-password" "Password hash is incorrect"
|
Expect.equal it.PasswordHash "hashed-password" "Password hash is incorrect"
|
||||||
Expect.equal it.Url (Some "https://example.com/~new") "URL is incorrect"
|
Expect.equal it.Url (Some "https://example.com/~new") "URL is incorrect"
|
||||||
Expect.equal it.AccessLevel Author "Access level is incorrect"
|
Expect.equal it.AccessLevel ContentAuthor "Access level is incorrect"
|
||||||
Expect.equal it.CreatedOn (Noda.epoch + Duration.FromDays 365) "Created on is incorrect"
|
Expect.equal it.CreatedOn (Noda.epoch + Duration.FromDays 365) "Created on is incorrect"
|
||||||
Expect.isNone it.LastSeenOn "Last seen on should not have had a value"
|
Expect.isNone it.LastSeenOn "Last seen on should not have had a value"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ let nodaTests = testList "Noda" [
|
|||||||
let accessLevelTests = testList "AccessLevel" [
|
let accessLevelTests = testList "AccessLevel" [
|
||||||
testList "Parse" [
|
testList "Parse" [
|
||||||
test "succeeds for \"Author\"" {
|
test "succeeds for \"Author\"" {
|
||||||
Expect.equal (AccessLevel.Parse "Author") Author "Author not parsed correctly"
|
Expect.equal (AccessLevel.Parse "Author") AccessLevel.ContentAuthor "Author not parsed correctly"
|
||||||
}
|
}
|
||||||
test "succeeds for \"Editor\"" {
|
test "succeeds for \"Editor\"" {
|
||||||
Expect.equal (AccessLevel.Parse "Editor") Editor "Editor not parsed correctly"
|
Expect.equal (AccessLevel.Parse "Editor") Editor "Editor not parsed correctly"
|
||||||
@@ -48,8 +48,8 @@ let accessLevelTests = testList "AccessLevel" [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
testList "ToString" [
|
testList "ToString" [
|
||||||
test "Author succeeds" {
|
test "ContentAuthor succeeds" {
|
||||||
Expect.equal (string Author) "Author" "Author string incorrect"
|
Expect.equal (string AccessLevel.ContentAuthor) "Author" "ContentAuthor string incorrect"
|
||||||
}
|
}
|
||||||
test "Editor succeeds" {
|
test "Editor succeeds" {
|
||||||
Expect.equal (string Editor) "Editor" "Editor string incorrect"
|
Expect.equal (string Editor) "Editor" "Editor string incorrect"
|
||||||
@@ -62,20 +62,20 @@ let accessLevelTests = testList "AccessLevel" [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
testList "HasAccess" [
|
testList "HasAccess" [
|
||||||
test "Author has Author access" {
|
test "ContentAuthor has ContentAuthor access" {
|
||||||
Expect.isTrue (Author.HasAccess Author) "Author should have Author access"
|
Expect.isTrue (ContentAuthor.HasAccess ContentAuthor) "ContentAuthor should have ContentAuthor access"
|
||||||
}
|
}
|
||||||
test "Author does not have Editor access" {
|
test "ContentAuthor does not have Editor access" {
|
||||||
Expect.isFalse (Author.HasAccess Editor) "Author should not have Editor access"
|
Expect.isFalse (ContentAuthor.HasAccess Editor) "ContentAuthor should not have Editor access"
|
||||||
}
|
}
|
||||||
test "Author does not have WebLogAdmin access" {
|
test "ContentAuthor does not have WebLogAdmin access" {
|
||||||
Expect.isFalse (Author.HasAccess WebLogAdmin) "Author should not have WebLogAdmin access"
|
Expect.isFalse (ContentAuthor.HasAccess WebLogAdmin) "ContentAuthor should not have WebLogAdmin access"
|
||||||
}
|
}
|
||||||
test "Author does not have Administrator access" {
|
test "ContentAuthor does not have Administrator access" {
|
||||||
Expect.isFalse (Author.HasAccess Administrator) "Author should not have Administrator access"
|
Expect.isFalse (ContentAuthor.HasAccess Administrator) "ContentAuthor should not have Administrator access"
|
||||||
}
|
}
|
||||||
test "Editor has Author access" {
|
test "Editor has ContentAuthor access" {
|
||||||
Expect.isTrue (Editor.HasAccess Author) "Editor should have Author access"
|
Expect.isTrue (Editor.HasAccess ContentAuthor) "Editor should have ContentAuthor access"
|
||||||
}
|
}
|
||||||
test "Editor has Editor access" {
|
test "Editor has Editor access" {
|
||||||
Expect.isTrue (Editor.HasAccess Editor) "Editor should have Editor access"
|
Expect.isTrue (Editor.HasAccess Editor) "Editor should have Editor access"
|
||||||
@@ -86,8 +86,8 @@ let accessLevelTests = testList "AccessLevel" [
|
|||||||
test "Editor does not have Administrator access" {
|
test "Editor does not have Administrator access" {
|
||||||
Expect.isFalse (Editor.HasAccess Administrator) "Editor should not have Administrator access"
|
Expect.isFalse (Editor.HasAccess Administrator) "Editor should not have Administrator access"
|
||||||
}
|
}
|
||||||
test "WebLogAdmin has Author access" {
|
test "WebLogAdmin has ContentAuthor access" {
|
||||||
Expect.isTrue (WebLogAdmin.HasAccess Author) "WebLogAdmin should have Author access"
|
Expect.isTrue (WebLogAdmin.HasAccess ContentAuthor) "WebLogAdmin should have ContentAuthor access"
|
||||||
}
|
}
|
||||||
test "WebLogAdmin has Editor access" {
|
test "WebLogAdmin has Editor access" {
|
||||||
Expect.isTrue (WebLogAdmin.HasAccess Editor) "WebLogAdmin should have Editor access"
|
Expect.isTrue (WebLogAdmin.HasAccess Editor) "WebLogAdmin should have Editor access"
|
||||||
@@ -98,8 +98,8 @@ let accessLevelTests = testList "AccessLevel" [
|
|||||||
test "WebLogAdmin does not have Administrator access" {
|
test "WebLogAdmin does not have Administrator access" {
|
||||||
Expect.isFalse (WebLogAdmin.HasAccess Administrator) "WebLogAdmin should not have Administrator access"
|
Expect.isFalse (WebLogAdmin.HasAccess Administrator) "WebLogAdmin should not have Administrator access"
|
||||||
}
|
}
|
||||||
test "Administrator has Author access" {
|
test "Administrator has ContentAuthor access" {
|
||||||
Expect.isTrue (Administrator.HasAccess Author) "Administrator should have Author access"
|
Expect.isTrue (Administrator.HasAccess ContentAuthor) "Administrator should have ContentAuthor access"
|
||||||
}
|
}
|
||||||
test "Administrator has Editor access" {
|
test "Administrator has Editor access" {
|
||||||
Expect.isTrue (Administrator.HasAccess Editor) "Administrator should have Editor access"
|
Expect.isTrue (Administrator.HasAccess Editor) "Administrator should have Editor access"
|
||||||
@@ -684,6 +684,93 @@ let openGraphPropertiesTests = testList "OpenGraphProperties" [
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/// Tests for the PersonGroup type
|
||||||
|
let personGroupTests = testList "PersonGroup" [
|
||||||
|
testList "Parse" [
|
||||||
|
test "succeeds for \"Administration\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Administration") Administration "Administration not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Audio Post-Production\"" {
|
||||||
|
Expect.equal
|
||||||
|
(PersonGroup.Parse "Audio Post-Production")
|
||||||
|
AudioPostProduction
|
||||||
|
"Audio Post-Production not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Audio Production\"" {
|
||||||
|
Expect.equal
|
||||||
|
(PersonGroup.Parse "Audio Production") AudioProduction "Audio Production not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Cast\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Cast") Cast "Cast not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Community\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Community") Community "Community not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Creative Direction\"" {
|
||||||
|
Expect.equal
|
||||||
|
(PersonGroup.Parse "Creative Direction") CreativeDirection "Creative Direction not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Misc.\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Misc.") Misc "Misc. not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Video Post-Production\"" {
|
||||||
|
Expect.equal
|
||||||
|
(PersonGroup.Parse "Video Post-Production")
|
||||||
|
VideoPostProduction
|
||||||
|
"Video Post-Production not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Video Production\"" {
|
||||||
|
Expect.equal
|
||||||
|
(PersonGroup.Parse "Video Production") VideoProduction "Video Production not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Visuals\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Visuals") Visuals "Visuals not parsed correctly"
|
||||||
|
}
|
||||||
|
test "succeeds for \"Writing\"" {
|
||||||
|
Expect.equal (PersonGroup.Parse "Writing") Writing "Writing not parsed correctly"
|
||||||
|
}
|
||||||
|
test "fails for unrecognized value" {
|
||||||
|
Expect.throwsT<ArgumentException>
|
||||||
|
(fun () -> ignore (PersonGroup.Parse "Fan")) "Invalid value should have raised an exception"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
testList "ToString" [
|
||||||
|
test "Administration succeeds" {
|
||||||
|
Expect.equal (string Administration) "Administration" "Administration string incorrect"
|
||||||
|
}
|
||||||
|
test "Audio Post-Production succeeds" {
|
||||||
|
Expect.equal (string AudioPostProduction) "Audio Post-Production" "Audio Post-Production string incorrect"
|
||||||
|
}
|
||||||
|
test "Audio Production succeeds" {
|
||||||
|
Expect.equal (string AudioProduction) "Audio Production" "Audio Production string incorrect"
|
||||||
|
}
|
||||||
|
test "Cast succeeds" {
|
||||||
|
Expect.equal (string Cast) "Cast" "Cast string incorrect"
|
||||||
|
}
|
||||||
|
test "Community succeeds" {
|
||||||
|
Expect.equal (string Community) "Community" "Community string incorrect"
|
||||||
|
}
|
||||||
|
test "Creative Direction succeeds" {
|
||||||
|
Expect.equal (string CreativeDirection) "Creative Direction" "Creative Direction string incorrect"
|
||||||
|
}
|
||||||
|
test "Misc succeeds" {
|
||||||
|
Expect.equal (string Misc) "Misc." "Misc string incorrect"
|
||||||
|
}
|
||||||
|
test "Video Post-Production succeeds" {
|
||||||
|
Expect.equal (string VideoPostProduction) "Video Post-Production" "Video Post-Production string incorrect"
|
||||||
|
}
|
||||||
|
test "Video Production succeeds" {
|
||||||
|
Expect.equal (string VideoProduction) "Video Production" "Video Production string incorrect"
|
||||||
|
}
|
||||||
|
test "Visuals succeeds" {
|
||||||
|
Expect.equal (string Visuals) "Visuals" "Visuals string incorrect"
|
||||||
|
}
|
||||||
|
test "Writing succeeds" {
|
||||||
|
Expect.equal (string Writing) "Writing" "Writing string incorrect"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
/// Unit tests for the PodcastMedium type
|
/// Unit tests for the PodcastMedium type
|
||||||
let podcastMediumTests = testList "PodcastMedium" [
|
let podcastMediumTests = testList "PodcastMedium" [
|
||||||
testList "Parse" [
|
testList "Parse" [
|
||||||
@@ -840,6 +927,7 @@ let all = testList "SupportTypes" [
|
|||||||
openGraphVideoTests
|
openGraphVideoTests
|
||||||
openGraphTypeTests
|
openGraphTypeTests
|
||||||
openGraphPropertiesTests
|
openGraphPropertiesTests
|
||||||
|
personGroupTests
|
||||||
podcastMediumTests
|
podcastMediumTests
|
||||||
postStatusTests
|
postStatusTests
|
||||||
customFeedSourceTests
|
customFeedSourceTests
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module Dashboard =
|
|||||||
|
|
||||||
// GET /admin/dashboard
|
// GET /admin/dashboard
|
||||||
let user : HttpHandler =
|
let user : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let getCount (f: WebLogId -> Task<int>) = f ctx.WebLog.Id
|
let getCount (f: WebLogId -> Task<int>) = f ctx.WebLog.Id
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ let private generateViewContext messages viewCtx (ctx: HttpContext) =
|
|||||||
CurrentPage = ctx.Request.Path.Value[1..]
|
CurrentPage = ctx.Request.Path.Value[1..]
|
||||||
Messages = messages
|
Messages = messages
|
||||||
Generator = ctx.Generator
|
Generator = ctx.Generator
|
||||||
IsAuthor = ctx.HasAccessLevel Author
|
IsAuthor = ctx.HasAccessLevel ContentAuthor
|
||||||
IsEditor = ctx.HasAccessLevel Editor
|
IsEditor = ctx.HasAccessLevel Editor
|
||||||
IsWebLogAdmin = ctx.HasAccessLevel WebLogAdmin
|
IsWebLogAdmin = ctx.HasAccessLevel WebLogAdmin
|
||||||
IsAdministrator = ctx.HasAccessLevel Administrator }
|
IsAdministrator = ctx.HasAccessLevel Administrator }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ open MyWebLog.ViewModels
|
|||||||
// GET /admin/pages
|
// GET /admin/pages
|
||||||
// GET /admin/pages/page/{pageNbr}
|
// GET /admin/pages/page/{pageNbr}
|
||||||
let all pageNbr : HttpHandler =
|
let all pageNbr : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! pages = ctx.Data.Page.FindPageOfPages ctx.WebLog.Id pageNbr
|
let! pages = ctx.Data.Page.FindPageOfPages ctx.WebLog.Id pageNbr
|
||||||
let displayPages =
|
let displayPages =
|
||||||
@@ -24,7 +24,7 @@ let all pageNbr : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/page/{id}/edit
|
// GET /admin/page/{id}/edit
|
||||||
let edit pgId : HttpHandler =
|
let edit pgId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! result = task {
|
let! result = task {
|
||||||
match pgId with
|
match pgId with
|
||||||
@@ -57,7 +57,7 @@ let delete pgId : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/page/{id}/permalinks
|
// GET /admin/page/{id}/permalinks
|
||||||
let editPermalinks pgId : HttpHandler =
|
let editPermalinks pgId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
||||||
| Some pg when canEdit pg.AuthorId ctx ->
|
| Some pg when canEdit pg.AuthorId ctx ->
|
||||||
@@ -71,7 +71,7 @@ let editPermalinks pgId : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/page/permalinks
|
// POST /admin/page/permalinks
|
||||||
let savePermalinks : HttpHandler =
|
let savePermalinks : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
||||||
@@ -90,7 +90,7 @@ let savePermalinks : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/page/{id}/revisions
|
// GET /admin/page/{id}/revisions
|
||||||
let editRevisions pgId : HttpHandler =
|
let editRevisions pgId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
||||||
| Some pg when canEdit pg.AuthorId ctx ->
|
| Some pg when canEdit pg.AuthorId ctx ->
|
||||||
@@ -104,7 +104,7 @@ let editRevisions pgId : HttpHandler =
|
|||||||
|
|
||||||
// DELETE /admin/page/{id}/revisions
|
// DELETE /admin/page/{id}/revisions
|
||||||
let purgeRevisions pgId : HttpHandler =
|
let purgeRevisions pgId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
match! data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
match! data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
||||||
@@ -128,7 +128,7 @@ let private findPageRevision pgId revDate (ctx: HttpContext) = task {
|
|||||||
|
|
||||||
// GET /admin/page/{id}/revision/{revision-date}/preview
|
// GET /admin/page/{id}/revision/{revision-date}/preview
|
||||||
let previewRevision (pgId, revDate) : HttpHandler =
|
let previewRevision (pgId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPageRevision pgId revDate ctx with
|
match! findPageRevision pgId revDate ctx with
|
||||||
| Some pg, Some rev when canEdit pg.AuthorId ctx ->
|
| Some pg, Some rev when canEdit pg.AuthorId ctx ->
|
||||||
@@ -139,7 +139,7 @@ let previewRevision (pgId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/page/{id}/revision/{revision-date}/restore
|
// POST /admin/page/{id}/revision/{revision-date}/restore
|
||||||
let restoreRevision (pgId, revDate) : HttpHandler =
|
let restoreRevision (pgId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPageRevision pgId revDate ctx with
|
match! findPageRevision pgId revDate ctx with
|
||||||
@@ -157,7 +157,7 @@ let restoreRevision (pgId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// DELETE /admin/page/{id}/revision/{revision-date}
|
// DELETE /admin/page/{id}/revision/{revision-date}
|
||||||
let deleteRevision (pgId, revDate) : HttpHandler =
|
let deleteRevision (pgId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPageRevision pgId revDate ctx with
|
match! findPageRevision pgId revDate ctx with
|
||||||
| Some pg, Some rev when canEdit pg.AuthorId ctx ->
|
| Some pg, Some rev when canEdit pg.AuthorId ctx ->
|
||||||
@@ -171,7 +171,7 @@ let deleteRevision (pgId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/page/save
|
// POST /admin/page/save
|
||||||
let save : HttpHandler =
|
let save : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! model = ctx.BindFormAsync<EditPageModel>()
|
let! model = ctx.BindFormAsync<EditPageModel>()
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ let chapters (post: Post) : HttpHandler = fun next ctx ->
|
|||||||
// GET /admin/posts
|
// GET /admin/posts
|
||||||
// GET /admin/posts/page/{pageNbr}
|
// GET /admin/posts/page/{pageNbr}
|
||||||
let all pageNbr : HttpHandler =
|
let all pageNbr : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
let! posts = data.Post.FindPageOfPosts ctx.WebLog.Id pageNbr 25
|
let! posts = data.Post.FindPageOfPosts ctx.WebLog.Id pageNbr 25
|
||||||
@@ -263,7 +263,7 @@ let all pageNbr : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/post/{id}/edit
|
// GET /admin/post/{id}/edit
|
||||||
let edit postId : HttpHandler =
|
let edit postId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
let! result = task {
|
let! result = task {
|
||||||
@@ -302,7 +302,7 @@ let delete postId : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/post/{id}/permalinks
|
// GET /admin/post/{id}/permalinks
|
||||||
let editPermalinks postId : HttpHandler =
|
let editPermalinks postId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
||||||
| Some post when canEdit post.AuthorId ctx ->
|
| Some post when canEdit post.AuthorId ctx ->
|
||||||
@@ -316,7 +316,7 @@ let editPermalinks postId : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/post/permalinks
|
// POST /admin/post/permalinks
|
||||||
let savePermalinks : HttpHandler =
|
let savePermalinks : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
||||||
@@ -335,7 +335,7 @@ let savePermalinks : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/post/{id}/revisions
|
// GET /admin/post/{id}/revisions
|
||||||
let editRevisions postId : HttpHandler =
|
let editRevisions postId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
||||||
| Some post when canEdit post.AuthorId ctx ->
|
| Some post when canEdit post.AuthorId ctx ->
|
||||||
@@ -349,7 +349,7 @@ let editRevisions postId : HttpHandler =
|
|||||||
|
|
||||||
// DELETE /admin/post/{id}/revisions
|
// DELETE /admin/post/{id}/revisions
|
||||||
let purgeRevisions postId : HttpHandler =
|
let purgeRevisions postId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
match! data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
match! data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
||||||
@@ -374,7 +374,7 @@ let private findPostRevision postId revDate (ctx: HttpContext) = task {
|
|||||||
|
|
||||||
// GET /admin/post/{id}/revision/{revision-date}/preview
|
// GET /admin/post/{id}/revision/{revision-date}/preview
|
||||||
let previewRevision (postId, revDate) : HttpHandler =
|
let previewRevision (postId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPostRevision postId revDate ctx with
|
match! findPostRevision postId revDate ctx with
|
||||||
| Some post, Some rev when canEdit post.AuthorId ctx ->
|
| Some post, Some rev when canEdit post.AuthorId ctx ->
|
||||||
@@ -385,7 +385,7 @@ let previewRevision (postId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/post/{id}/revision/{revision-date}/restore
|
// POST /admin/post/{id}/revision/{revision-date}/restore
|
||||||
let restoreRevision (postId, revDate) : HttpHandler =
|
let restoreRevision (postId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPostRevision postId revDate ctx with
|
match! findPostRevision postId revDate ctx with
|
||||||
@@ -403,7 +403,7 @@ let restoreRevision (postId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// DELETE /admin/post/{id}/revision/{revision-date}
|
// DELETE /admin/post/{id}/revision/{revision-date}
|
||||||
let deleteRevision (postId, revDate) : HttpHandler =
|
let deleteRevision (postId, revDate) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! findPostRevision postId revDate ctx with
|
match! findPostRevision postId revDate ctx with
|
||||||
| Some post, Some rev when canEdit post.AuthorId ctx ->
|
| Some post, Some rev when canEdit post.AuthorId ctx ->
|
||||||
@@ -417,7 +417,7 @@ let deleteRevision (postId, revDate) : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/post/{id}/chapters
|
// GET /admin/post/{id}/chapters
|
||||||
let manageChapters postId : HttpHandler =
|
let manageChapters postId : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||||
| Some post
|
| Some post
|
||||||
@@ -432,7 +432,7 @@ let manageChapters postId : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/post/{id}/chapter/{idx}
|
// GET /admin/post/{id}/chapter/{idx}
|
||||||
let editChapter (postId, index) : HttpHandler =
|
let editChapter (postId, index) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||||
| Some post
|
| Some post
|
||||||
@@ -455,7 +455,7 @@ let editChapter (postId, index) : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/post/{id}/chapter/{idx}
|
// POST /admin/post/{id}/chapter/{idx}
|
||||||
let saveChapter (postId, index) : HttpHandler =
|
let saveChapter (postId, index) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
@@ -488,7 +488,7 @@ let saveChapter (postId, index) : HttpHandler =
|
|||||||
|
|
||||||
// DELETE /admin/post/{id}/chapter/{idx}
|
// DELETE /admin/post/{id}/chapter/{idx}
|
||||||
let deleteChapter (postId, index) : HttpHandler =
|
let deleteChapter (postId, index) : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let data = ctx.Data
|
let data = ctx.Data
|
||||||
match! data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
match! data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||||
@@ -512,7 +512,7 @@ let deleteChapter (postId, index) : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/post/save
|
// POST /admin/post/save
|
||||||
let save : HttpHandler =
|
let save : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! model = ctx.BindFormAsync<EditPostModel>()
|
let! model = ctx.BindFormAsync<EditPostModel>()
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ let makeSlug it = (Regex """\s+""").Replace((Regex "[^A-z0-9 -]").Replace(it, ""
|
|||||||
|
|
||||||
// GET /admin/uploads
|
// GET /admin/uploads
|
||||||
let list : HttpHandler =
|
let list : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let webLog = ctx.WebLog
|
let webLog = ctx.WebLog
|
||||||
let! dbUploads = ctx.Data.Upload.FindByWebLog webLog.Id
|
let! dbUploads = ctx.Data.Upload.FindByWebLog webLog.Id
|
||||||
@@ -127,12 +127,12 @@ let list : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/upload/new
|
// GET /admin/upload/new
|
||||||
let showNew : HttpHandler =
|
let showNew : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> adminPage "Upload a File" next ctx Views.WebLog.uploadNew
|
>=> fun next ctx -> adminPage "Upload a File" next ctx Views.WebLog.uploadNew
|
||||||
|
|
||||||
// POST /admin/upload/save
|
// POST /admin/upload/save
|
||||||
let save : HttpHandler =
|
let save : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
if ctx.Request.HasFormContentType && ctx.Request.Form.Files.Count > 0 then
|
if ctx.Request.HasFormContentType && ctx.Request.Form.Files.Count > 0 then
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ let delete userId : HttpHandler =
|
|||||||
|
|
||||||
// GET /admin/my-info
|
// GET /admin/my-info
|
||||||
let myInfo : HttpHandler =
|
let myInfo : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
match! ctx.Data.WebLogUser.FindById ctx.UserId ctx.WebLog.Id with
|
match! ctx.Data.WebLogUser.FindById ctx.UserId ctx.WebLog.Id with
|
||||||
| Some user ->
|
| Some user ->
|
||||||
@@ -154,7 +154,7 @@ let myInfo : HttpHandler =
|
|||||||
|
|
||||||
// POST /admin/my-info
|
// POST /admin/my-info
|
||||||
let saveMyInfo : HttpHandler =
|
let saveMyInfo : HttpHandler =
|
||||||
requireAccess Author
|
requireAccess ContentAuthor
|
||||||
>=> validateCsrf
|
>=> validateCsrf
|
||||||
>=> fun next ctx -> task {
|
>=> fun next ctx -> task {
|
||||||
let! model = ctx.BindFormAsync<EditMyInfoModel>()
|
let! model = ctx.BindFormAsync<EditMyInfoModel>()
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ let userList (model: WebLogUser list) app =
|
|||||||
| Administrator -> span [ _class $"{badge}-success" ] [ raw "ADMINISTRATOR" ]
|
| Administrator -> span [ _class $"{badge}-success" ] [ raw "ADMINISTRATOR" ]
|
||||||
| WebLogAdmin -> span [ _class $"{badge}-primary" ] [ raw "WEB LOG ADMIN" ]
|
| WebLogAdmin -> span [ _class $"{badge}-primary" ] [ raw "WEB LOG ADMIN" ]
|
||||||
| Editor -> span [ _class $"{badge}-secondary" ] [ raw "EDITOR" ]
|
| Editor -> span [ _class $"{badge}-secondary" ] [ raw "EDITOR" ]
|
||||||
| Author -> span [ _class $"{badge}-dark" ] [ raw "AUTHOR" ]
|
| ContentAuthor -> span [ _class $"{badge}-dark" ] [ raw "AUTHOR" ]
|
||||||
br []
|
br []
|
||||||
if app.IsAdministrator || (app.IsWebLogAdmin && not (user.AccessLevel = Administrator)) then
|
if app.IsAdministrator || (app.IsWebLogAdmin && not (user.AccessLevel = Administrator)) then
|
||||||
let userUrl = relUrl app $"admin/settings/user/{user.Id}"
|
let userUrl = relUrl app $"admin/settings/user/{user.Id}"
|
||||||
|
|||||||
Reference in New Issue
Block a user