Skip to content

Commit ac8fd96

Browse files
committed
WIP: mutation
1 parent 81d9862 commit ac8fd96

File tree

6 files changed

+385
-3
lines changed

6 files changed

+385
-3
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
* Licensed to The Apereo Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
*
7+
* The Apereo Foundation licenses this file to you under the Educational
8+
* Community License, Version 2.0 (the "License"); you may not use this file
9+
* except in compliance with the License. You may obtain a copy of the License
10+
* at:
11+
*
12+
* http://opensource.org/licenses/ecl2.txt
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+
* License for the specific language governing permissions and limitations under
18+
* the License.
19+
*
20+
*/
21+
22+
package org.opencastproject.graphql.command;
23+
24+
import org.opencastproject.authorization.xacml.manager.api.AclService;
25+
import org.opencastproject.authorization.xacml.manager.api.AclServiceFactory;
26+
import org.opencastproject.graphql.exception.GraphQLRuntimeException;
27+
import org.opencastproject.graphql.exception.GraphQLUnauthorizedException;
28+
import org.opencastproject.graphql.execution.context.OpencastContext;
29+
import org.opencastproject.graphql.execution.context.OpencastContextManager;
30+
import org.opencastproject.graphql.playlist.GqlPlaylist;
31+
import org.opencastproject.graphql.playlist.PlaylistEntriesInput;
32+
import org.opencastproject.graphql.playlist.PlaylistMetadataInput;
33+
import org.opencastproject.graphql.type.input.AccessControlListInput;
34+
import org.opencastproject.graphql.util.GraphQLObjectMapper;
35+
import org.opencastproject.playlists.Playlist;
36+
import org.opencastproject.playlists.PlaylistAccessControlEntry;
37+
import org.opencastproject.playlists.PlaylistEntry;
38+
import org.opencastproject.playlists.PlaylistEntryType;
39+
import org.opencastproject.playlists.PlaylistService;
40+
import org.opencastproject.security.api.AccessControlEntry;
41+
import org.opencastproject.security.api.AccessControlList;
42+
import org.opencastproject.security.api.SecurityService;
43+
import org.opencastproject.security.api.UnauthorizedException;
44+
45+
import java.util.ArrayList;
46+
import java.util.List;
47+
48+
/**
49+
* Command to create a playlist from GraphQL inputs (metadata, entries, acl).
50+
*/
51+
public class CreatePlaylistCommand extends AbstractCommand<GqlPlaylist> {
52+
53+
private final PlaylistMetadataInput metadataInput;
54+
private final PlaylistEntriesInput entriesInput;
55+
private final AccessControlListInput aclInput;
56+
57+
public CreatePlaylistCommand(final Builder builder) {
58+
super(builder);
59+
this.metadataInput = builder.metadataInput;
60+
this.entriesInput = builder.entriesInput;
61+
this.aclInput = builder.aclInput;
62+
}
63+
64+
@Override
65+
public GqlPlaylist execute() {
66+
OpencastContext context = OpencastContextManager.getCurrentContext();
67+
final PlaylistService playlistService = context.getService(PlaylistService.class);
68+
69+
try {
70+
// read arguments from environment when present, otherwise fall back to builder values
71+
final Object metadataArg = environment.getArgument("metadata");
72+
final PlaylistMetadataInput metadata = metadataArg == null
73+
? metadataInput
74+
: GraphQLObjectMapper.newInstance().convertValue(metadataArg, PlaylistMetadataInput.class);
75+
76+
final Object entriesArg = environment.getArgument("entries");
77+
final PlaylistEntriesInput entries = entriesArg == null
78+
? entriesInput
79+
: GraphQLObjectMapper.newInstance().convertValue(entriesArg, PlaylistEntriesInput.class);
80+
81+
// Build playlist from inputs
82+
Playlist playlist = new Playlist();
83+
if (metadata != null) {
84+
playlist.setTitle(metadata.getTitle());
85+
playlist.setDescription(metadata.getDescription());
86+
playlist.setCreator(metadata.getCreator());
87+
// organization is optional and set by PlaylistService if missing
88+
}
89+
90+
// Entries
91+
List<PlaylistEntry> playlistEntries = new ArrayList<>();
92+
if (entries != null && entries.getEntries() != null) {
93+
for (var entryInput : entries.getEntries()) {
94+
PlaylistEntryType type = PlaylistEntryType.EVENT;
95+
if (entryInput != null && entryInput.getType() != null) {
96+
type = entryInput.getType().getType();
97+
}
98+
PlaylistEntry pe = new PlaylistEntry(entryInput == null ? null : entryInput.getContentId(), type);
99+
playlistEntries.add(pe);
100+
}
101+
}
102+
playlist.setEntries(playlistEntries);
103+
104+
// ACL
105+
AccessControlList acl = new AccessControlList();
106+
final AccessControlListInput aclToUse = this.aclInput == null ? environment.getArgument("acl") == null ? null
107+
: GraphQLObjectMapper.newInstance().convertValue(environment.getArgument("acl"), AccessControlListInput.class)
108+
: this.aclInput;
109+
110+
if (aclToUse != null) {
111+
if (aclToUse.getEntries() != null) {
112+
for (var item : aclToUse.getEntries()) {
113+
for (var action : item.getAction()) {
114+
acl.getEntries().add(new AccessControlEntry(item.getRole(), action, true));
115+
}
116+
}
117+
}
118+
if (aclToUse.getManagedAclId() != null) {
119+
AclService aclService = context.getService(AclServiceFactory.class)
120+
.serviceFor(context.getService(SecurityService.class).getOrganization());
121+
aclService.getAcl(aclToUse.getManagedAclId()).ifPresent(value -> acl.merge(value.getAcl()));
122+
}
123+
}
124+
125+
List<PlaylistAccessControlEntry> aceList = new ArrayList<>();
126+
for (AccessControlEntry entry : acl.getEntries()) {
127+
aceList.add(new PlaylistAccessControlEntry(entry.isAllow(), entry.getRole(), entry.getAction()));
128+
}
129+
playlist.setAccessControlEntries(aceList);
130+
131+
// Persist
132+
playlist = playlistService.update(playlist);
133+
134+
return new GqlPlaylist(playlist);
135+
} catch (UnauthorizedException e) {
136+
throw new GraphQLUnauthorizedException(e.getMessage());
137+
} catch (RuntimeException e) {
138+
throw new GraphQLRuntimeException(e);
139+
}
140+
}
141+
142+
public static Builder create(
143+
PlaylistMetadataInput metadataInput,
144+
PlaylistEntriesInput entriesInput,
145+
AccessControlListInput accessControlListInput) {
146+
return new Builder(metadataInput, entriesInput, accessControlListInput);
147+
}
148+
149+
public static class Builder extends AbstractCommand.Builder<GqlPlaylist> {
150+
151+
private final PlaylistMetadataInput metadataInput;
152+
private final PlaylistEntriesInput entriesInput;
153+
private final AccessControlListInput aclInput;
154+
155+
public Builder(PlaylistMetadataInput metadataInput, PlaylistEntriesInput entriesInput,
156+
AccessControlListInput aclInput) {
157+
this.metadataInput = metadataInput;
158+
this.entriesInput = entriesInput;
159+
this.aclInput = aclInput;
160+
}
161+
162+
@Override
163+
public void validate() {
164+
super.validate();
165+
if (metadataInput == null) {
166+
throw new IllegalStateException("Playlist metadata cannot be null");
167+
}
168+
if (aclInput == null) {
169+
throw new IllegalStateException("Access control list cannot be null");
170+
}
171+
}
172+
173+
@Override
174+
public CreatePlaylistCommand build() {
175+
validate();
176+
return new CreatePlaylistCommand(this);
177+
}
178+
}
179+
180+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Licensed to The Apereo Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
*
7+
* The Apereo Foundation licenses this file to you under the Educational
8+
* Community License, Version 2.0 (the "License"); you may not use this file
9+
* except in compliance with the License. You may obtain a copy of the License
10+
* at:
11+
*
12+
* http://opensource.org/licenses/ecl2.txt
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+
* License for the specific language governing permissions and limitations under
18+
* the License.
19+
*
20+
*/
21+
22+
package org.opencastproject.graphql.playlist;
23+
24+
25+
import graphql.annotations.annotationTypes.GraphQLField;
26+
import graphql.annotations.annotationTypes.GraphQLName;
27+
import graphql.annotations.annotationTypes.GraphQLNonNull;
28+
29+
@GraphQLName(PlaylistEntriesInput.TYPE_NAME)
30+
public class PlaylistEntriesInput {
31+
public static final String TYPE_NAME = "PlaylistEntriesInput";
32+
33+
@GraphQLField
34+
@GraphQLNonNull
35+
private java.util.List<PlaylistEntryInput> entries;
36+
37+
public PlaylistEntriesInput() { }
38+
39+
public java.util.List<PlaylistEntryInput> getEntries() {
40+
return entries;
41+
}
42+
}
43+
44+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Licensed to The Apereo Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
*
7+
* The Apereo Foundation licenses this file to you under the Educational
8+
* Community License, Version 2.0 (the "License"); you may not use this file
9+
* except in compliance with the License. You may obtain a copy of the License
10+
* at:
11+
*
12+
* http://opensource.org/licenses/ecl2.txt
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+
* License for the specific language governing permissions and limitations under
18+
* the License.
19+
*
20+
*/
21+
22+
package org.opencastproject.graphql.playlist;
23+
24+
import graphql.annotations.annotationTypes.GraphQLField;
25+
import graphql.annotations.annotationTypes.GraphQLName;
26+
27+
@GraphQLName(PlaylistEntryInput.TYPE_NAME)
28+
public class PlaylistEntryInput {
29+
public static final String TYPE_NAME = "PlaylistEntryInput";
30+
31+
@GraphQLField
32+
private String contentId;
33+
34+
@GraphQLField
35+
private GqlPlaylistEntryType type;
36+
37+
public PlaylistEntryInput() { }
38+
39+
public String getContentId() {
40+
return contentId;
41+
}
42+
43+
public GqlPlaylistEntryType getType() {
44+
return type;
45+
}
46+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Licensed to The Apereo Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
*
7+
* The Apereo Foundation licenses this file to you under the Educational
8+
* Community License, Version 2.0 (the "License"); you may not use this file
9+
* except in compliance with the License. You may obtain a copy of the License
10+
* at:
11+
*
12+
* http://opensource.org/licenses/ecl2.txt
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+
* License for the specific language governing permissions and limitations under
18+
* the License.
19+
*
20+
*/
21+
package org.opencastproject.graphql.playlist;
22+
23+
import graphql.annotations.annotationTypes.GraphQLField;
24+
import graphql.annotations.annotationTypes.GraphQLName;
25+
26+
@GraphQLName(PlaylistMetadataInput.TYPE_NAME)
27+
public class PlaylistMetadataInput {
28+
29+
public static final String TYPE_NAME = "PlaylistMetadataInput";
30+
31+
@GraphQLField
32+
private String title;
33+
34+
@GraphQLField
35+
private String description;
36+
37+
@GraphQLField
38+
private String creator;
39+
40+
public PlaylistMetadataInput() {
41+
}
42+
43+
public PlaylistMetadataInput(String title, String description, String creator) {
44+
this.title = title;
45+
this.description = description;
46+
this.creator = creator;
47+
}
48+
49+
public String getTitle() {
50+
return title;
51+
}
52+
53+
public String getDescription() {
54+
return description;
55+
}
56+
57+
public String getCreator() {
58+
return creator;
59+
}
60+
61+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Licensed to The Apereo Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
*
7+
* The Apereo Foundation licenses this file to you under the Educational
8+
* Community License, Version 2.0 (the "License"); you may not use this file
9+
* except in compliance with the License. You may obtain a copy of the License
10+
* at:
11+
*
12+
* http://opensource.org/licenses/ecl2.txt
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
17+
* License for the specific language governing permissions and limitations under
18+
* the License.
19+
*
20+
*/
21+
22+
package org.opencastproject.graphql.playlist;
23+
24+
import org.opencastproject.graphql.command.CreatePlaylistCommand;
25+
import org.opencastproject.graphql.type.input.AccessControlListInput;
26+
import org.opencastproject.graphql.type.input.Mutation;
27+
28+
import graphql.annotations.annotationTypes.GraphQLDescription;
29+
import graphql.annotations.annotationTypes.GraphQLField;
30+
import graphql.annotations.annotationTypes.GraphQLName;
31+
import graphql.annotations.annotationTypes.GraphQLNonNull;
32+
import graphql.annotations.annotationTypes.GraphQLTypeExtension;
33+
import graphql.schema.DataFetchingEnvironment;
34+
35+
@GraphQLTypeExtension(Mutation.class)
36+
public final class PlaylistMutationExtension {
37+
38+
private PlaylistMutationExtension() {
39+
}
40+
41+
@GraphQLField
42+
@GraphQLDescription("Create playlist from metadata, entries and acl")
43+
public static GqlPlaylist createPlaylist(
44+
@GraphQLName("metadata") @GraphQLNonNull PlaylistMetadataInput metadata,
45+
@GraphQLName("entries") PlaylistEntriesInput entries,
46+
@GraphQLName("acl") @GraphQLNonNull AccessControlListInput acl,
47+
final DataFetchingEnvironment environment) {
48+
return CreatePlaylistCommand.create(metadata, entries, acl)
49+
.environment(environment)
50+
.build()
51+
.execute();
52+
}
53+
54+
}

0 commit comments

Comments
 (0)