1// Copyright 2017 Frédéric Guillot. All rights reserved.
2// Use of this source code is governed by the Apache 2.0
3// license that can be found in the LICENSE file.
4
5package api // import "miniflux.app/api"
6
7import (
8	json_parser "encoding/json"
9	"errors"
10	"net/http"
11
12	"miniflux.app/http/request"
13	"miniflux.app/http/response/json"
14	"miniflux.app/model"
15	"miniflux.app/validator"
16)
17
18func (h *handler) currentUser(w http.ResponseWriter, r *http.Request) {
19	user, err := h.store.UserByID(request.UserID(r))
20	if err != nil {
21		json.ServerError(w, r, err)
22		return
23	}
24
25	json.OK(w, r, user)
26}
27
28func (h *handler) createUser(w http.ResponseWriter, r *http.Request) {
29	if !request.IsAdminUser(r) {
30		json.Forbidden(w, r)
31		return
32	}
33
34	var userCreationRequest model.UserCreationRequest
35	if err := json_parser.NewDecoder(r.Body).Decode(&userCreationRequest); err != nil {
36		json.BadRequest(w, r, err)
37		return
38	}
39
40	if validationErr := validator.ValidateUserCreationWithPassword(h.store, &userCreationRequest); validationErr != nil {
41		json.BadRequest(w, r, validationErr.Error())
42		return
43	}
44
45	user, err := h.store.CreateUser(&userCreationRequest)
46	if err != nil {
47		json.ServerError(w, r, err)
48		return
49	}
50
51	json.Created(w, r, user)
52}
53
54func (h *handler) updateUser(w http.ResponseWriter, r *http.Request) {
55	userID := request.RouteInt64Param(r, "userID")
56
57	var userModificationRequest model.UserModificationRequest
58	if err := json_parser.NewDecoder(r.Body).Decode(&userModificationRequest); err != nil {
59		json.BadRequest(w, r, err)
60		return
61	}
62
63	originalUser, err := h.store.UserByID(userID)
64	if err != nil {
65		json.ServerError(w, r, err)
66		return
67	}
68
69	if originalUser == nil {
70		json.NotFound(w, r)
71		return
72	}
73
74	if !request.IsAdminUser(r) {
75		if originalUser.ID != request.UserID(r) {
76			json.Forbidden(w, r)
77			return
78		}
79
80		if userModificationRequest.IsAdmin != nil && *userModificationRequest.IsAdmin {
81			json.BadRequest(w, r, errors.New("Only administrators can change permissions of standard users"))
82			return
83		}
84	}
85
86	if validationErr := validator.ValidateUserModification(h.store, originalUser.ID, &userModificationRequest); validationErr != nil {
87		json.BadRequest(w, r, validationErr.Error())
88		return
89	}
90
91	userModificationRequest.Patch(originalUser)
92	if err = h.store.UpdateUser(originalUser); err != nil {
93		json.ServerError(w, r, err)
94		return
95	}
96
97	json.Created(w, r, originalUser)
98}
99
100func (h *handler) markUserAsRead(w http.ResponseWriter, r *http.Request) {
101	userID := request.RouteInt64Param(r, "userID")
102	if userID != request.UserID(r) {
103		json.Forbidden(w, r)
104		return
105	}
106
107	if _, err := h.store.UserByID(userID); err != nil {
108		json.NotFound(w, r)
109		return
110	}
111
112	if err := h.store.MarkAllAsRead(userID); err != nil {
113		json.ServerError(w, r, err)
114		return
115	}
116
117	json.NoContent(w, r)
118}
119
120func (h *handler) users(w http.ResponseWriter, r *http.Request) {
121	if !request.IsAdminUser(r) {
122		json.Forbidden(w, r)
123		return
124	}
125
126	users, err := h.store.Users()
127	if err != nil {
128		json.ServerError(w, r, err)
129		return
130	}
131
132	users.UseTimezone(request.UserTimezone(r))
133	json.OK(w, r, users)
134}
135
136func (h *handler) userByID(w http.ResponseWriter, r *http.Request) {
137	if !request.IsAdminUser(r) {
138		json.Forbidden(w, r)
139		return
140	}
141
142	userID := request.RouteInt64Param(r, "userID")
143	user, err := h.store.UserByID(userID)
144	if err != nil {
145		json.BadRequest(w, r, errors.New("Unable to fetch this user from the database"))
146		return
147	}
148
149	if user == nil {
150		json.NotFound(w, r)
151		return
152	}
153
154	user.UseTimezone(request.UserTimezone(r))
155	json.OK(w, r, user)
156}
157
158func (h *handler) userByUsername(w http.ResponseWriter, r *http.Request) {
159	if !request.IsAdminUser(r) {
160		json.Forbidden(w, r)
161		return
162	}
163
164	username := request.RouteStringParam(r, "username")
165	user, err := h.store.UserByUsername(username)
166	if err != nil {
167		json.BadRequest(w, r, errors.New("Unable to fetch this user from the database"))
168		return
169	}
170
171	if user == nil {
172		json.NotFound(w, r)
173		return
174	}
175
176	json.OK(w, r, user)
177}
178
179func (h *handler) removeUser(w http.ResponseWriter, r *http.Request) {
180	if !request.IsAdminUser(r) {
181		json.Forbidden(w, r)
182		return
183	}
184
185	userID := request.RouteInt64Param(r, "userID")
186	user, err := h.store.UserByID(userID)
187	if err != nil {
188		json.ServerError(w, r, err)
189		return
190	}
191
192	if user == nil {
193		json.NotFound(w, r)
194		return
195	}
196
197	if user.ID == request.UserID(r) {
198		json.BadRequest(w, r, errors.New("You cannot remove yourself"))
199		return
200	}
201
202	h.store.RemoveUserAsync(user.ID)
203	json.NoContent(w, r)
204}
205