def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 一覧ファイル取得 pages = json.loads( file_utils.get_file(self.request.wiki_id, "pages.json")) pages = pages["data"]["pages"] pages = sorted(pages, key=lambda x: x['update'], reverse=True) for page in pages: file_name_slash = file_name_tools.file_name_to_page_name( page["file_name"]) page["file_name"] = file_name_slash argzz = [self.request.wiki_id] argzz.extend(file_name_slash.split("/")) page["url"] = reverse('wikis.pages:show', args=argzz) tdatetime = datetime.datetime.strptime(page["update"], '%Y-%m-%dT%H:%M:%S.%f') page["update_day"] = datetime.date(tdatetime.year, tdatetime.month, tdatetime.day) page["update"] = tdatetime context["pages"] = pages return context
def get_comments_short(wiki_id, page_name): logger.debug("get_comments_short:start") file_name = file_name_tools.page_name_to_file_name(page_name) try: comment_data = file_utils.get_file(wiki_id, file_name + ".comments.json") comment_data = json.loads(comment_data) comments = [] for comment in reversed(comment_data["comments"]): comment["children"] = [] comment["hierarchy"] = 0 comments.append(comment) logger.debug("get_comments_short:end") return comments except FileNotFoundError: logger.debug("comment file not found") logger.debug("get_comments_short:end") # ファイルが存在しない場合は空リストを返却する。 return []
def get_or_new(wiki_id, file_name): """ コメントを階層構造で取得する。 :param wiki_id: :param file_name: :return: """ logger.debug("get_or_new:start") try: comment_data = file_utils.get_file(wiki_id, file_name + ".attachments.json") comment_data = json.loads(comment_data) logger.debug("get_or_new:end") return comment_data except FileNotFoundError: logger.debug("comment file not found") new_comment_data = { "file_type": "attachment", "attachments": [], } logger.debug("get_or_new:end") return new_comment_data
def sitemap(request, wiki_id): page_file = json.loads(file_utils.get_file(wiki_id, "pages.json")) pages = page_file["data"]["pages"] pages = sorted(pages, key=lambda x: x['update'], reverse=True) for page in pages: file_name_slash = file_name_tools.file_name_to_page_name( page["file_name"]) page["file_name"] = file_name_slash argzz = [wiki_id] argzz.extend(file_name_slash.split("/")) loc = "{}://{}{}".format(request.get_raw_uri().split(":")[0], request.get_host(), reverse('wikis.pages:show', args=argzz)) page["loc"] = loc tdatetime = datetime.datetime.strptime(page["update"], '%Y-%m-%dT%H:%M:%S.%f') tdate = datetime.date(tdatetime.year, tdatetime.month, tdatetime.day).strftime('%Y-%m-%dT%H:%M:%SZ') page["lastmod"] = tdate context = {"wiki_id": wiki_id, "pages": pages} html = render_to_string("wikis/pages/sitemap.xml", context) return HttpResponse(html, content_type="application/xhtml+xml")
def put_page_file(self, timestamp): # wikiID wiki_id = self.data["wiki_id"] # ファイル名 file_name = file_name_tools.page_name_to_file_name( self.data["page_name"]) # ページ一覧ファイルを取得する。 page_file = json.loads(file_utils.get_file(wiki_id, "pages.json")) # 内容が空になったら削除として扱う。 # 一覧から見えなくなるだけでファイルや履歴は残る。 status = "active" if self.data["contents"] else "inactive" # ページ一覧を更新する。 # 新規作成の場合はレコードの新規追加、更新の場合はレコード更新。 # 注意事項 # ページ一覧は異なる新規登録・編集の操作から同時に更新される可能性がある。 # (一つのファイルに対する更新処理の競合) # 競合が発生した場合は後勝ちになるため、 # 「ページを新規追加したにも関わらず、ページ一覧に記載が無い」という状況が発生する余地がある。 # このため新規作成 or 更新の判定は、どの画面から操作が行われたかではなく、 # 一覧に対象ページが存在するかどうかで判定する。 # 「ページ一覧に記載が無い」が発生した場合、同画面を空更新することで一覧に追記可能である。(運用回避) # ファイル中に該当ページがあった場合、更新する。 for page in page_file["data"]["pages"]: if page["file_name"] == file_name: page["update"] = timestamp page["status"] = status page_file["update"] = timestamp file_utils.put_file(wiki_id, "pages.json", json.dumps(page_file)) return # ファイル中に該当ページが無かった場合、新規追加する。 page_file["data"]["pages"].append({ "file_name": file_name, "extension": "md", "create": timestamp, "update": timestamp, "status": status }) page_file["create"] = timestamp page_file["update"] = timestamp file_utils.put_file(wiki_id, "pages.json", json.dumps(page_file))
def put(self): # wikiID wiki_id = self.data["wiki_id"] # confファイル取得 wiki_conf = json.loads(file_utils.get_file(wiki_id, "config.json")) wiki_conf["name"] = self.data["name"] wiki_conf["confs"]['comment_mode'] = self.data["comment_mode"] wiki_conf["confs"]['edit_authority'] = self.data["edit_authority"] wiki_conf["confs"]['release_status'] = self.data["release_status"] wiki_conf["updated_at"] = datetime.now().isoformat() file_utils.put_file(wiki_id, "config.json", json.dumps(wiki_conf))
def get_comments_hierarchy(wiki_id, page_dirs): """ コメントを階層構造で取得する。 :param wiki_id: :param page_dirs: :return: """ logger.debug("get_comments_hierarchy:start") file_name = file_name_tools.page_dirs_to_file_name(page_dirs) try: comment_data = file_utils.get_file(wiki_id, file_name + ".comments.json") comment_data = json.loads(comment_data) comment_dict = {} for comment in comment_data["comments"]: comment["children"] = [] comment["hierarchy"] = 0 comment_dict["comment_" + str(comment["id"])] = comment comment_list_root = [] for key in comment_dict: comment = comment_dict[key] if comment["parent"] != 0: comment_dict["comment_" + str(comment["parent"])]["children"].append(key) else: comment_list_root.append(comment) comment_list = [] for comment in comment_list_root: comment_list.append(comment) comment_list = _recursion_children(comment_list, comment_dict, comment, 1) logger.debug("get_comments_hierarchy:end") return comment_list except FileNotFoundError: logger.debug("comment file not found") logger.debug("get_comments_hierarchy:end") # ファイルが存在しない場合は空リストを返却する。 return []
def get_edit_contents(wiki_id, page_dirs): logger.debug("get_edit_contents:start") try: page_name = file_name_tools.page_dirs_to_file_name(page_dirs) get_page_file_data = file_utils.get_file(wiki_id, page_name + ".md") except FileNotFoundError: raise PageNotFoundError("ページが存在しません。") logger.debug("get_edit_contents:end") return get_page_file_data
def __init__(self, wiki_id, **kwargs): super().__init__(**kwargs) wiki_conf = json.loads(file_utils.get_file(wiki_id, "config.json")) self.fields['wiki_id'].initial = wiki_id self.fields['name'].initial = wiki_conf["name"] confs = wiki_conf["confs"] self.fields['comment_mode'].initial = confs.get("comment_mode") \ if "comment_mode" in confs else self.fields['comment_mode'].initial self.fields['edit_authority'].initial = confs.get("edit_authority") \ if "edit_authority" in confs else self.fields['edit_authority'].initial self.fields['release_status'].initial = confs.get("release_status") \ if "release_status" in confs else self.fields['release_status'].initial
def put(self): # ページのファイルパスを取得 file_name = file_name_tools.page_name_to_file_name( self.data["page_name"]) # コメントデータを取得 comment_file_data = comment_tool.get_or_new(self.data["wiki_id"], file_name) # タイムスタンプ timestamp = datetime.now().isoformat() # 匿名の場合は名無しさんとする name = self.data["name"] if self.data["name"] else "名無しさん" # 次のシーケンス番号 next_id = len(comment_file_data["comments"]) + 1 comment_file_data["comments"].append({ "id": next_id, "name": name, "body": self.data["body"], "timestamp": datetime.now().isoformat(), "parent": int(self.data["parent"]) }) if not "created_at" in comment_file_data: comment_file_data["created_at"] = timestamp comment_file_data["updated_at"] = timestamp # コメントファイルを保存する。 file_utils.put_file(self.data["wiki_id"], file_name + ".comments.json", json.dumps(comment_file_data)) page_conf_file = file_utils.get_file(self.data["wiki_id"], file_name + ".confs.json") page_conf = json.loads(page_conf_file) page_conf["confs"]["comment_exist_flg"] = True file_utils.put_file(self.data["wiki_id"], file_name + ".confs.json", json.dumps(page_conf))
def clean_page_name(self): # wikiID wiki_id = self.data["wiki_id"] # ページ名 page_name = self.cleaned_data['page_name'] # NGword # URLのパスと重複するIDを禁止する。 ngname = [ "attachment", "attachments", "comment", "comments", "history", "histories", "maintenance", "maintenances", "page", "pages", "create", "copy", "list", "updates", "help", "sitemap.xml", ] page_dirs = file_name_tools.to_page_dirs(page_name) if page_dirs[0] in ngname: raise forms.ValidationError('対象のページ名は予約語であるため、使用出来ません。') # ファイル名 file_name = file_name_tools.page_name_to_file_name(page_name) # ページ一覧 page_file = json.loads(file_utils.get_file(wiki_id, "pages.json")) pages = page_file["data"]["pages"] # 新規作成するページが既に存在していないかチェック for page in pages: if file_name == page["file_name"]: raise forms.ValidationError("対象のページは既に存在しています。") return page_name
def put(self): # wikiID wiki_id = self.data["wiki_id"] file_name = file_name_tools.page_name_to_file_name( self.data["page_name"]) + ".confs.json" # confファイル取得 page_conf_file = file_utils.get_file(wiki_id, file_name) page_conf = json.loads(page_conf_file) page_conf["confs"]['comment_mode'] = self.data["comment_mode"] page_conf["confs"]['attachment_mode'] = self.data["attachment_mode"] page_conf["confs"]['freeze_mode'] = self.data["freeze_mode"] page_conf["updated_at"] = datetime.now().isoformat() file_utils.put_file(wiki_id, file_name, json.dumps(page_conf))
def initialize(self, request, *args, **kwargs): if hasattr(self.request, "initialized_flg"): return self.request.initialized_flg = True my_kwargs = self.get_my_kwargs(**kwargs) request.wiki_id = my_kwargs.get("wiki_id") try: wiki_conf_file = file_utils.get_file(request.wiki_id, "config.json") request.wiki_conf = json.loads(wiki_conf_file) except FileNotFoundError: request.wiki_conf = None
def initialize(self, request, *args, **kwargs): if hasattr(self.request, "initialized_flg"): return super().initialize(request, *args, **kwargs) self.request.page_dirs = self.get_page_dirs(**kwargs) try: page_conf_file = file_utils.get_file( request.wiki_id, file_name_tools.page_dirs_to_file_name(request.page_dirs) + ".confs.json") request.page_conf = json.loads(page_conf_file) except FileNotFoundError: request.page_conf = None
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # ページの設定ファイルを取得 file_name = file_name_tools.page_dirs_to_file_name(super().get_page_dirs()) history_file = file_utils.get_file(self.request.wiki_id, file_name + ".histories.json") history_file = json.loads(history_file) history_before = None for history in history_file["histories"]: if history_before: history["before_history_file_path"] = history_before["history_file_path"] history["timestamp"] = datetime.strptime(history["timestamp"], "%Y-%m-%dT%H:%M:%S.%f") history_before = history context["history_file"] = history_file return context
def __init__(self, wiki_id, page_dirs, **kwargs): super().__init__(**kwargs) file_name = file_name_tools.page_dirs_to_file_name( page_dirs) + ".confs.json" page_conf_file = file_utils.get_file(wiki_id, file_name) page_conf = json.loads(page_conf_file) self.fields['wiki_id'].initial = wiki_id self.fields[ 'page_name'].initial = file_name_tools.page_dirs_to_page_name( page_dirs) confs = page_conf["confs"] self.fields['comment_mode'].initial = confs.get("comment_mode") \ if "comment_mode" in confs else self.fields['comment_mode'].initial self.fields['attachment_mode'].initial = confs.get("attachment_mode") \ if "attachment_mode" in confs else self.fields['attachment_mode'].initial self.fields['freeze_mode'].initial = confs.get("freeze_mode") \ if "freeze_mode" in confs else self.fields['freeze_mode'].initial
def put(self, request): # リクエストからipアドレスを、セッションからログイン情報を取得するが、 # 必ず取得出来るものではない。 client_ip, is_routable = get_client_ip(request) client_ip = client_ip if client_ip else "0.0.0.0" user_digest = request.session.get('user_digest') user_digest = user_digest if user_digest else "anonymous" logger.info("更新者情報:user_digest=%s / client_ip=%s", user_digest, client_ip) # wikiID wiki_id = self.data["wiki_id"] # ファイル名 file_name = file_name_tools.page_name_to_file_name( self.data["page_name"]) # タイムスタンプ timestamp = datetime.now().isoformat() # ページの履歴ファイルを取得 history_file = file_utils.get_file(wiki_id, file_name + ".histories.json") history_file = json.loads(history_file) # 最後(現在)の履歴を取得 last_history = history_file["histories"][-1] # 最終更新日時 last_history_timestamp = datetime.strptime(last_history["timestamp"], "%Y-%m-%dT%H:%M:%S.%f") # 最終更新から一時間以内に再更新した場合、履歴を追加しない。 # 「ちょっと更新して保存」を繰り返すことで残す価値の履歴が増えてしまうことを回避するための措置 if last_history_timestamp > datetime.now() - timedelta(hours=1): # ページを保存する。 file_utils.put_file(wiki_id, file_name + ".md", self.data["contents"]) # 内容が空になったら削除として扱う。 # 一覧から見えなくなるだけでファイルや履歴は残る。 comment = "updated" if self.data["contents"] else "deleted" last_history["name"] = os.path.basename(file_name) last_history["timestamp"] = timestamp last_history["comment"] = comment last_history["client_ip"] = client_ip last_history["user_digest"] = user_digest else: # 現在のページをバックアップする。 backup_file_name = file_name + "." + last_history_timestamp.strftime( "%Y%m%d%H%M%S%f") file_utils.put_history(wiki_id, file_name + ".md", backup_file_name + ".md") # ページを保存する。 file_utils.put_file(wiki_id, file_name + ".md", self.data["contents"]) # バックアップ情報を履歴に追記する。 last_history["history_file_path"] = backup_file_name + ".md" history_file["histories"][-1] = last_history # 内容が空になったら削除として扱う。 # 一覧から見えなくなるだけでファイルや履歴は残る。 comment = "updated" if self.data["contents"] else "deleted" # 新しい履歴を追加する。 history_file["histories"].append({ "name": os.path.basename(file_name), "timestamp": timestamp, "comment": comment, "client_ip": client_ip, "user_digest": user_digest, }) history_file["updated_at"] = timestamp # 履歴ファイルを更新する。 file_utils.put_file(wiki_id, file_name + ".histories.json", json.dumps(history_file)) # ページ一覧を更新する。 super().put_page_file(timestamp)