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) =
|
||||
(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>
|
||||
type PermalinkConverter() =
|
||||
inherit JsonConverter<Permalink>()
|
||||
@@ -92,13 +100,21 @@ module Json =
|
||||
override _.ReadJson(reader: JsonReader, _: Type, _: Permalink, _: bool, _: JsonSerializer) =
|
||||
(string >> Permalink) reader.Value
|
||||
|
||||
/// <summary>Converter for the <see cref="PageId" /> type</summary>
|
||||
type PageIdConverter() =
|
||||
inherit JsonConverter<PageId>()
|
||||
override _.WriteJson(writer: JsonWriter, value: PageId, _: JsonSerializer) =
|
||||
/// <summary>Converter for the <see cref="PersonGroup" /> type</summary>
|
||||
type PersonGroupConverter() =
|
||||
inherit JsonConverter<PersonGroup>()
|
||||
override _.WriteJson(writer: JsonWriter, value: PersonGroup, _: JsonSerializer) =
|
||||
writer.WriteValue(string value)
|
||||
override _.ReadJson(reader: JsonReader, _: Type, _: PageId, _: bool, _: JsonSerializer) =
|
||||
(string >> PageId) reader.Value
|
||||
override _.ReadJson(reader: JsonReader, _: Type, _: PersonGroup, _: bool, _: JsonSerializer) =
|
||||
(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>
|
||||
type PodcastMediumConverter() =
|
||||
@@ -180,8 +196,10 @@ module Json =
|
||||
ExplicitRatingConverter()
|
||||
MarkupTextConverter()
|
||||
OpenGraphTypeConverter()
|
||||
PermalinkConverter()
|
||||
PageIdConverter()
|
||||
PermalinkConverter()
|
||||
PersonGroupConverter()
|
||||
PersonRoleConverter()
|
||||
PodcastMediumConverter()
|
||||
PostIdConverter()
|
||||
TagMapIdConverter()
|
||||
|
||||
@@ -457,7 +457,7 @@ type WebLogUser = {
|
||||
PreferredName = ""
|
||||
PasswordHash = ""
|
||||
Url = None
|
||||
AccessLevel = Author
|
||||
AccessLevel = ContentAuthor
|
||||
CreatedOn = Noda.epoch
|
||||
LastSeenOn = None }
|
||||
|
||||
|
||||
@@ -61,18 +61,22 @@ module Noda =
|
||||
/// <summary>A user's access level</summary>
|
||||
[<Struct>]
|
||||
type AccessLevel =
|
||||
|
||||
/// <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>
|
||||
| Editor
|
||||
|
||||
/// <summary>The user may delete posts and configure web log settings</summary>
|
||||
| WebLogAdmin
|
||||
|
||||
/// <summary>The user may manage themes (which affects all web logs for an installation)</summary>
|
||||
| Administrator
|
||||
|
||||
/// <summary>Weights applied to each access level</summary>
|
||||
static member private Weights =
|
||||
[ Author, 10
|
||||
[ ContentAuthor, 10
|
||||
Editor, 20
|
||||
WebLogAdmin, 30
|
||||
Administrator, 40 ]
|
||||
@@ -84,7 +88,7 @@ type AccessLevel =
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse level =
|
||||
match level with
|
||||
| "Author" -> Author
|
||||
| "Author" -> ContentAuthor
|
||||
| "Editor" -> Editor
|
||||
| "WebLogAdmin" -> WebLogAdmin
|
||||
| "Administrator" -> Administrator
|
||||
@@ -93,7 +97,7 @@ type AccessLevel =
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Author -> "Author"
|
||||
| ContentAuthor -> "Author"
|
||||
| Editor -> "Editor"
|
||||
| WebLogAdmin -> "WebLogAdmin"
|
||||
| Administrator -> "Administrator"
|
||||
@@ -269,6 +273,331 @@ type Chapter = {
|
||||
EndTime = 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
|
||||
|
||||
|
||||
@@ -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
|
||||
let permalinkConverterTests = testList "PermalinkConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
@@ -150,17 +164,31 @@ let permalinkConverterTests = testList "PermalinkConverter" [
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PageIdConverter type
|
||||
let pageIdConverterTests = testList "PageIdConverter" [
|
||||
/// Unit tests for the PersonGroupConverter type
|
||||
let personGroupConverterTests = testList "PersonGroupConverter" [
|
||||
let opts = JsonSerializerSettings()
|
||||
opts.Converters.Add(PageIdConverter())
|
||||
opts.Converters.Add(PersonGroupConverter())
|
||||
test "succeeds when serializing" {
|
||||
let after = JsonConvert.SerializeObject(PageId "test-page", opts)
|
||||
Expect.equal after "\"test-page\"" "Page ID serialized incorrectly"
|
||||
let after = JsonConvert.SerializeObject(Visuals, opts)
|
||||
Expect.equal after "\"Visuals\"" "PersonGroup serialized incorrectly"
|
||||
}
|
||||
test "succeeds when deserializing" {
|
||||
let after = JsonConvert.DeserializeObject<PageId>("\"page-test\"", opts)
|
||||
Expect.equal after (PageId "page-test") "Page ID deserialized incorrectly"
|
||||
let after = JsonConvert.DeserializeObject<PersonGroup>("\"Cast\"", opts)
|
||||
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<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<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<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<PostIdConverter>) "Post 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
|
||||
markupTextConverterTests
|
||||
openGraphTypeConverterTests
|
||||
permalinkConverterTests
|
||||
pageIdConverterTests
|
||||
permalinkConverterTests
|
||||
personGroupConverterTests
|
||||
personRoleConverterTests
|
||||
podcastMediumConverterTests
|
||||
postIdConverterTests
|
||||
tagMapIdConverterTests
|
||||
|
||||
@@ -33,7 +33,7 @@ let ``Add succeeds`` (data: IData) = task {
|
||||
PreferredName = "n00b"
|
||||
PasswordHash = "hashed-password"
|
||||
Url = Some "https://example.com/~new"
|
||||
AccessLevel = Author
|
||||
AccessLevel = ContentAuthor
|
||||
CreatedOn = Noda.epoch + Duration.FromDays 365
|
||||
LastSeenOn = None }
|
||||
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.PasswordHash "hashed-password" "Password hash 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.isNone it.LastSeenOn "Last seen on should not have had a value"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ let nodaTests = testList "Noda" [
|
||||
let accessLevelTests = testList "AccessLevel" [
|
||||
testList "Parse" [
|
||||
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\"" {
|
||||
Expect.equal (AccessLevel.Parse "Editor") Editor "Editor not parsed correctly"
|
||||
@@ -48,8 +48,8 @@ let accessLevelTests = testList "AccessLevel" [
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "Author succeeds" {
|
||||
Expect.equal (string Author) "Author" "Author string incorrect"
|
||||
test "ContentAuthor succeeds" {
|
||||
Expect.equal (string AccessLevel.ContentAuthor) "Author" "ContentAuthor string incorrect"
|
||||
}
|
||||
test "Editor succeeds" {
|
||||
Expect.equal (string Editor) "Editor" "Editor string incorrect"
|
||||
@@ -62,20 +62,20 @@ let accessLevelTests = testList "AccessLevel" [
|
||||
}
|
||||
]
|
||||
testList "HasAccess" [
|
||||
test "Author has Author access" {
|
||||
Expect.isTrue (Author.HasAccess Author) "Author should have Author access"
|
||||
test "ContentAuthor has ContentAuthor access" {
|
||||
Expect.isTrue (ContentAuthor.HasAccess ContentAuthor) "ContentAuthor should have ContentAuthor access"
|
||||
}
|
||||
test "Author does not have Editor access" {
|
||||
Expect.isFalse (Author.HasAccess Editor) "Author should not have Editor access"
|
||||
test "ContentAuthor does not have Editor access" {
|
||||
Expect.isFalse (ContentAuthor.HasAccess Editor) "ContentAuthor should not have Editor access"
|
||||
}
|
||||
test "Author does not have WebLogAdmin access" {
|
||||
Expect.isFalse (Author.HasAccess WebLogAdmin) "Author should not have WebLogAdmin access"
|
||||
test "ContentAuthor does not have WebLogAdmin access" {
|
||||
Expect.isFalse (ContentAuthor.HasAccess WebLogAdmin) "ContentAuthor should not have WebLogAdmin access"
|
||||
}
|
||||
test "Author does not have Administrator access" {
|
||||
Expect.isFalse (Author.HasAccess Administrator) "Author should not have Administrator access"
|
||||
test "ContentAuthor does not have Administrator access" {
|
||||
Expect.isFalse (ContentAuthor.HasAccess Administrator) "ContentAuthor should not have Administrator access"
|
||||
}
|
||||
test "Editor has Author access" {
|
||||
Expect.isTrue (Editor.HasAccess Author) "Editor should have Author access"
|
||||
test "Editor has ContentAuthor access" {
|
||||
Expect.isTrue (Editor.HasAccess ContentAuthor) "Editor should have ContentAuthor access"
|
||||
}
|
||||
test "Editor has 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" {
|
||||
Expect.isFalse (Editor.HasAccess Administrator) "Editor should not have Administrator access"
|
||||
}
|
||||
test "WebLogAdmin has Author access" {
|
||||
Expect.isTrue (WebLogAdmin.HasAccess Author) "WebLogAdmin should have Author access"
|
||||
test "WebLogAdmin has ContentAuthor access" {
|
||||
Expect.isTrue (WebLogAdmin.HasAccess ContentAuthor) "WebLogAdmin should have ContentAuthor access"
|
||||
}
|
||||
test "WebLogAdmin has 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" {
|
||||
Expect.isFalse (WebLogAdmin.HasAccess Administrator) "WebLogAdmin should not have Administrator access"
|
||||
}
|
||||
test "Administrator has Author access" {
|
||||
Expect.isTrue (Administrator.HasAccess Author) "Administrator should have Author access"
|
||||
test "Administrator has ContentAuthor access" {
|
||||
Expect.isTrue (Administrator.HasAccess ContentAuthor) "Administrator should have ContentAuthor access"
|
||||
}
|
||||
test "Administrator has 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
|
||||
let podcastMediumTests = testList "PodcastMedium" [
|
||||
testList "Parse" [
|
||||
@@ -840,6 +927,7 @@ let all = testList "SupportTypes" [
|
||||
openGraphVideoTests
|
||||
openGraphTypeTests
|
||||
openGraphPropertiesTests
|
||||
personGroupTests
|
||||
podcastMediumTests
|
||||
postStatusTests
|
||||
customFeedSourceTests
|
||||
|
||||
@@ -13,7 +13,7 @@ module Dashboard =
|
||||
|
||||
// GET /admin/dashboard
|
||||
let user : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let getCount (f: WebLogId -> Task<int>) = f ctx.WebLog.Id
|
||||
let data = ctx.Data
|
||||
|
||||
@@ -88,7 +88,7 @@ let private generateViewContext messages viewCtx (ctx: HttpContext) =
|
||||
CurrentPage = ctx.Request.Path.Value[1..]
|
||||
Messages = messages
|
||||
Generator = ctx.Generator
|
||||
IsAuthor = ctx.HasAccessLevel Author
|
||||
IsAuthor = ctx.HasAccessLevel ContentAuthor
|
||||
IsEditor = ctx.HasAccessLevel Editor
|
||||
IsWebLogAdmin = ctx.HasAccessLevel WebLogAdmin
|
||||
IsAdministrator = ctx.HasAccessLevel Administrator }
|
||||
|
||||
@@ -8,7 +8,7 @@ open MyWebLog.ViewModels
|
||||
// GET /admin/pages
|
||||
// GET /admin/pages/page/{pageNbr}
|
||||
let all pageNbr : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let! pages = ctx.Data.Page.FindPageOfPages ctx.WebLog.Id pageNbr
|
||||
let displayPages =
|
||||
@@ -24,7 +24,7 @@ let all pageNbr : HttpHandler =
|
||||
|
||||
// GET /admin/page/{id}/edit
|
||||
let edit pgId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let! result = task {
|
||||
match pgId with
|
||||
@@ -57,7 +57,7 @@ let delete pgId : HttpHandler =
|
||||
|
||||
// GET /admin/page/{id}/permalinks
|
||||
let editPermalinks pgId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
||||
| Some pg when canEdit pg.AuthorId ctx ->
|
||||
@@ -71,7 +71,7 @@ let editPermalinks pgId : HttpHandler =
|
||||
|
||||
// POST /admin/page/permalinks
|
||||
let savePermalinks : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
||||
@@ -90,7 +90,7 @@ let savePermalinks : HttpHandler =
|
||||
|
||||
// GET /admin/page/{id}/revisions
|
||||
let editRevisions pgId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Page.FindFullById (PageId pgId) ctx.WebLog.Id with
|
||||
| Some pg when canEdit pg.AuthorId ctx ->
|
||||
@@ -104,7 +104,7 @@ let editRevisions pgId : HttpHandler =
|
||||
|
||||
// DELETE /admin/page/{id}/revisions
|
||||
let purgeRevisions pgId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
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
|
||||
let previewRevision (pgId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! findPageRevision pgId revDate ctx with
|
||||
| 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
|
||||
let restoreRevision (pgId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
match! findPageRevision pgId revDate ctx with
|
||||
@@ -157,7 +157,7 @@ let restoreRevision (pgId, revDate) : HttpHandler =
|
||||
|
||||
// DELETE /admin/page/{id}/revision/{revision-date}
|
||||
let deleteRevision (pgId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! findPageRevision pgId revDate ctx with
|
||||
| Some pg, Some rev when canEdit pg.AuthorId ctx ->
|
||||
@@ -171,7 +171,7 @@ let deleteRevision (pgId, revDate) : HttpHandler =
|
||||
|
||||
// POST /admin/page/save
|
||||
let save : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let! model = ctx.BindFormAsync<EditPageModel>()
|
||||
|
||||
@@ -253,7 +253,7 @@ let chapters (post: Post) : HttpHandler = fun next ctx ->
|
||||
// GET /admin/posts
|
||||
// GET /admin/posts/page/{pageNbr}
|
||||
let all pageNbr : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
let! posts = data.Post.FindPageOfPosts ctx.WebLog.Id pageNbr 25
|
||||
@@ -263,7 +263,7 @@ let all pageNbr : HttpHandler =
|
||||
|
||||
// GET /admin/post/{id}/edit
|
||||
let edit postId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
let! result = task {
|
||||
@@ -302,7 +302,7 @@ let delete postId : HttpHandler =
|
||||
|
||||
// GET /admin/post/{id}/permalinks
|
||||
let editPermalinks postId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
||||
| Some post when canEdit post.AuthorId ctx ->
|
||||
@@ -316,7 +316,7 @@ let editPermalinks postId : HttpHandler =
|
||||
|
||||
// POST /admin/post/permalinks
|
||||
let savePermalinks : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let! model = ctx.BindFormAsync<ManagePermalinksModel>()
|
||||
@@ -335,7 +335,7 @@ let savePermalinks : HttpHandler =
|
||||
|
||||
// GET /admin/post/{id}/revisions
|
||||
let editRevisions postId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Post.FindFullById (PostId postId) ctx.WebLog.Id with
|
||||
| Some post when canEdit post.AuthorId ctx ->
|
||||
@@ -349,7 +349,7 @@ let editRevisions postId : HttpHandler =
|
||||
|
||||
// DELETE /admin/post/{id}/revisions
|
||||
let purgeRevisions postId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
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
|
||||
let previewRevision (postId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! findPostRevision postId revDate ctx with
|
||||
| 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
|
||||
let restoreRevision (postId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
match! findPostRevision postId revDate ctx with
|
||||
@@ -403,7 +403,7 @@ let restoreRevision (postId, revDate) : HttpHandler =
|
||||
|
||||
// DELETE /admin/post/{id}/revision/{revision-date}
|
||||
let deleteRevision (postId, revDate) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! findPostRevision postId revDate ctx with
|
||||
| Some post, Some rev when canEdit post.AuthorId ctx ->
|
||||
@@ -417,7 +417,7 @@ let deleteRevision (postId, revDate) : HttpHandler =
|
||||
|
||||
// GET /admin/post/{id}/chapters
|
||||
let manageChapters postId : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||
| Some post
|
||||
@@ -432,7 +432,7 @@ let manageChapters postId : HttpHandler =
|
||||
|
||||
// GET /admin/post/{id}/chapter/{idx}
|
||||
let editChapter (postId, index) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||
| Some post
|
||||
@@ -455,7 +455,7 @@ let editChapter (postId, index) : HttpHandler =
|
||||
|
||||
// POST /admin/post/{id}/chapter/{idx}
|
||||
let saveChapter (postId, index) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
@@ -488,7 +488,7 @@ let saveChapter (postId, index) : HttpHandler =
|
||||
|
||||
// DELETE /admin/post/{id}/chapter/{idx}
|
||||
let deleteChapter (postId, index) : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let data = ctx.Data
|
||||
match! data.Post.FindById (PostId postId) ctx.WebLog.Id with
|
||||
@@ -512,7 +512,7 @@ let deleteChapter (postId, index) : HttpHandler =
|
||||
|
||||
// POST /admin/post/save
|
||||
let save : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let! model = ctx.BindFormAsync<EditPostModel>()
|
||||
|
||||
@@ -91,7 +91,7 @@ let makeSlug it = (Regex """\s+""").Replace((Regex "[^A-z0-9 -]").Replace(it, ""
|
||||
|
||||
// GET /admin/uploads
|
||||
let list : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
let webLog = ctx.WebLog
|
||||
let! dbUploads = ctx.Data.Upload.FindByWebLog webLog.Id
|
||||
@@ -127,12 +127,12 @@ let list : HttpHandler =
|
||||
|
||||
// GET /admin/upload/new
|
||||
let showNew : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> adminPage "Upload a File" next ctx Views.WebLog.uploadNew
|
||||
|
||||
// POST /admin/upload/save
|
||||
let save : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
if ctx.Request.HasFormContentType && ctx.Request.Form.Files.Count > 0 then
|
||||
|
||||
@@ -142,7 +142,7 @@ let delete userId : HttpHandler =
|
||||
|
||||
// GET /admin/my-info
|
||||
let myInfo : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> fun next ctx -> task {
|
||||
match! ctx.Data.WebLogUser.FindById ctx.UserId ctx.WebLog.Id with
|
||||
| Some user ->
|
||||
@@ -154,7 +154,7 @@ let myInfo : HttpHandler =
|
||||
|
||||
// POST /admin/my-info
|
||||
let saveMyInfo : HttpHandler =
|
||||
requireAccess Author
|
||||
requireAccess ContentAuthor
|
||||
>=> validateCsrf
|
||||
>=> fun next ctx -> task {
|
||||
let! model = ctx.BindFormAsync<EditMyInfoModel>()
|
||||
|
||||
@@ -133,7 +133,7 @@ let userList (model: WebLogUser list) app =
|
||||
| Administrator -> span [ _class $"{badge}-success" ] [ raw "ADMINISTRATOR" ]
|
||||
| WebLogAdmin -> span [ _class $"{badge}-primary" ] [ raw "WEB LOG ADMIN" ]
|
||||
| Editor -> span [ _class $"{badge}-secondary" ] [ raw "EDITOR" ]
|
||||
| Author -> span [ _class $"{badge}-dark" ] [ raw "AUTHOR" ]
|
||||
| ContentAuthor -> span [ _class $"{badge}-dark" ] [ raw "AUTHOR" ]
|
||||
br []
|
||||
if app.IsAdministrator || (app.IsWebLogAdmin && not (user.AccessLevel = Administrator)) then
|
||||
let userUrl = relUrl app $"admin/settings/user/{user.Id}"
|
||||
|
||||
Reference in New Issue
Block a user